diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/botserv.cpp | 20 | ||||
| -rw-r--r-- | src/channels.cpp | 19 | ||||
| -rw-r--r-- | src/chanserv.cpp | 5 | ||||
| -rw-r--r-- | src/commands.cpp | 25 | ||||
| -rw-r--r-- | src/config.cpp | 15 | ||||
| -rw-r--r-- | src/hostserv.cpp | 5 | ||||
| -rw-r--r-- | src/init.cpp | 4 | ||||
| -rw-r--r-- | src/language.cpp | 5698 | ||||
| -rw-r--r-- | src/mail.cpp | 21 | ||||
| -rw-r--r-- | src/memoserv.cpp | 58 | ||||
| -rw-r--r-- | src/messages.cpp | 14 | ||||
| -rw-r--r-- | src/misc.cpp | 42 | ||||
| -rw-r--r-- | src/module.cpp | 20 | ||||
| -rw-r--r-- | src/modulemanager.cpp | 9 | ||||
| -rw-r--r-- | src/modules.cpp | 118 | ||||
| -rw-r--r-- | src/nickserv.cpp | 17 | ||||
| -rw-r--r-- | src/operserv.cpp | 41 | ||||
| -rw-r--r-- | src/regchannel.cpp | 5 | ||||
| -rw-r--r-- | src/send.cpp | 72 | ||||
| -rw-r--r-- | src/sessions.cpp | 10 | ||||
| -rw-r--r-- | src/users.cpp | 30 |
21 files changed, 5598 insertions, 650 deletions
diff --git a/src/botserv.cpp b/src/botserv.cpp index 4cfd42e5b..cf5d6fa10 100644 --- a/src/botserv.cpp +++ b/src/botserv.cpp @@ -13,12 +13,11 @@ #include "services.h" #include "modules.h" -#include "language.h" static UserData *get_user_data(Channel *c, User *u); static void check_ban(ChannelInfo *ci, User *u, int ttbtype); -static void bot_kick(ChannelInfo *ci, User *u, int message, ...); +static void bot_kick(ChannelInfo *ci, User *u, LanguageString message, ...); E void moduleAddBotServCmds(); @@ -488,20 +487,19 @@ static void check_ban(ChannelInfo *ci, User *u, int ttbtype) /* This makes a bot kick an user. Works somewhat like notice_lang in fact ;) */ -static void bot_kick(ChannelInfo *ci, User *u, int message, ...) +static void bot_kick(ChannelInfo *ci, User *u, LanguageString message, ...) { va_list args; char buf[1024]; - const char *fmt; if (!ci || !ci->bi || !ci->c || !u) return; + Anope::string fmt = GetString(u, message); va_start(args, message); - fmt = getstring(u, message); - if (!fmt) + if (fmt.empty()) return; - vsnprintf(buf, sizeof(buf), fmt, args); + vsnprintf(buf, sizeof(buf), fmt.c_str(), args); va_end(args); ci->c->Kick(ci->bi, u, "%s", buf); @@ -521,7 +519,7 @@ void bot_raw_ban(User *requester, ChannelInfo *ci, const Anope::string &nick, co if (ModeManager::FindUserModeByName(UMODE_PROTECTED) && u->IsProtected() && requester != u) { - ircdproto->SendPrivmsg(ci->bi, ci->name, "%s", getstring(ACCESS_DENIED)); + ircdproto->SendPrivmsg(ci->bi, ci->name, "%s", GetString(requester, ACCESS_DENIED).c_str()); return; } @@ -530,7 +528,7 @@ void bot_raw_ban(User *requester, ChannelInfo *ci, const Anope::string &nick, co if (ModeManager::FindChannelModeByName(CMODE_EXCEPT) && is_excepted(ci, u) == 1) { - ircdproto->SendPrivmsg(ci->bi, ci->name, "%s", getstring(BOT_EXCEPT)); + ircdproto->SendPrivmsg(ci->bi, ci->name, "%s", GetString(requester, BOT_EXCEPT).c_str()); return; } @@ -558,7 +556,7 @@ void bot_raw_kick(User *requester, ChannelInfo *ci, const Anope::string &nick, c if (ModeManager::FindUserModeByName(UMODE_PROTECTED) && u->IsProtected() && requester != u) { - ircdproto->SendPrivmsg(ci->bi, ci->name, "%s", getstring(ACCESS_DENIED)); + ircdproto->SendPrivmsg(ci->bi, ci->name, "%s", GetString(requester, ACCESS_DENIED).c_str()); return; } @@ -589,7 +587,7 @@ void bot_raw_mode(User *requester, ChannelInfo *ci, const Anope::string &mode, c if (ModeManager::FindUserModeByName(UMODE_PROTECTED) && u->IsProtected() && mode[0] == '-' && requester != u) { - ircdproto->SendPrivmsg(ci->bi, ci->name, "%s", getstring(ACCESS_DENIED)); + ircdproto->SendPrivmsg(ci->bi, ci->name, "%s", GetString(requester, ACCESS_DENIED).c_str()); return; } diff --git a/src/channels.cpp b/src/channels.cpp index 8a500d759..84870b1e9 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -10,7 +10,6 @@ */ #include "services.h" -#include "language.h" #include "modules.h" channel_map ChannelList; @@ -145,9 +144,9 @@ void Channel::JoinUser(User *user) if (this->ci && check_access(user, this->ci, CA_MEMO) && this->ci->memos.memos.size() > 0) { if (this->ci->memos.memos.size() == 1) - notice_lang(Config->s_MemoServ, user, MEMO_X_ONE_NOTICE, this->ci->memos.memos.size(), this->ci->name.c_str()); + user->SendMessage(MemoServ, MEMO_X_ONE_NOTICE, this->ci->memos.memos.size(), this->ci->name.c_str()); else - notice_lang(Config->s_MemoServ, user, MEMO_X_MANY_NOTICE, this->ci->memos.memos.size(), this->ci->name.c_str()); + user->SendMessage(MemoServ, MEMO_X_MANY_NOTICE, this->ci->memos.memos.size(), this->ci->name.c_str()); } /* Added channelname to entrymsg - 30.03.2004, Certus */ /* Also, don't send the entrymsg when bursting -GD */ @@ -453,13 +452,6 @@ void Channel::RemoveModeInternal(ChannelMode *cm, const Anope::string ¶m, bo bi = findbot(param); User *u = bi ? bi : finduser(param); - /* Reset modes on bots if we're supposed to */ - if (bi) - { - if (std::find(Config->BotModeList.begin(), Config->BotModeList.end(), cm) != Config->BotModeList.end()) - this->SetMode(bi, cm, bi->nick); - } - if (!u) { Log() << "Channel::RemoveModeInternal() MODE " << this->name << "-" << cm->ModeChar << " for nonexistant user " << param; @@ -473,6 +465,13 @@ void Channel::RemoveModeInternal(ChannelMode *cm, const Anope::string ¶m, bo if (cc) cc->Status->UnsetFlag(cm->Name); + /* Reset modes on bots if we're supposed to */ + if (bi) + { + if (std::find(Config->BotModeList.begin(), Config->BotModeList.end(), cm) != Config->BotModeList.end()) + this->SetMode(bi, cm, bi->nick); + } + return; } /* Setting b/e/I etc */ diff --git a/src/chanserv.cpp b/src/chanserv.cpp index b2dffcfd2..25c0cbf36 100644 --- a/src/chanserv.cpp +++ b/src/chanserv.cpp @@ -13,7 +13,6 @@ #include "services.h" #include "modules.h" -#include "language.h" registered_channel_map RegisteredChannelList; @@ -354,7 +353,7 @@ int check_valid_admin(User *user, Channel *chan, int servermode) if (servermode && !check_access(user, chan->ci, CA_AUTOPROTECT)) { - notice_lang(Config->s_ChanServ, user, CHAN_IS_REGISTERED, Config->s_ChanServ.c_str()); + user->SendMessage(ChanServ, CHAN_IS_REGISTERED, Config->s_ChanServ.c_str()); chan->RemoveMode(NULL, CMODE_PROTECT, user->nick); return 0; } @@ -390,7 +389,7 @@ int check_valid_op(User *user, Channel *chan, int servermode) if (servermode && !check_access(user, chan->ci, CA_AUTOOP)) { - notice_lang(Config->s_ChanServ, user, CHAN_IS_REGISTERED, Config->s_ChanServ.c_str()); + user->SendMessage(ChanServ, CHAN_IS_REGISTERED, Config->s_ChanServ.c_str()); if (owner) chan->RemoveMode(NULL, CMODE_OWNER, user->nick); diff --git a/src/commands.cpp b/src/commands.cpp index bbf2a5233..3dc9ea177 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -11,7 +11,6 @@ #include "services.h" #include "modules.h" -#include "language.h" #include "hashcomp.h" Command *FindCommand(BotInfo *bi, const Anope::string &name) @@ -50,14 +49,14 @@ void mod_run_cmd(BotInfo *bi, User *u, Command *c, const Anope::string &command, if (!c) { - notice_lang(bi->nick, u, UNKNOWN_COMMAND_HELP, command.c_str(), bi->nick.c_str()); + u->SendMessage(bi, UNKNOWN_COMMAND_HELP, command.c_str(), bi->nick.c_str()); return; } // Command requires registered users only if (!c->HasFlag(CFLAG_ALLOW_UNREGISTERED) && !u->IsIdentified()) { - notice_lang(bi->nick, u, NICK_IDENTIFY_REQUIRED, Config->s_NickServ.c_str()); + u->SendMessage(bi, NICK_IDENTIFY_REQUIRED, Config->s_NickServ.c_str()); Log(LOG_COMMAND, "denied", bi) << "Access denied for unregistered user " << u->GetMask() << " with command " << command; return; } @@ -102,27 +101,27 @@ void mod_run_cmd(BotInfo *bi, User *u, Command *c, const Anope::string &command, { if (ci->HasFlag(CI_FORBIDDEN) && !c->HasFlag(CFLAG_ALLOW_FORBIDDEN)) { - notice_lang(bi->nick, u, CHAN_X_FORBIDDEN, ci->name.c_str()); + u->SendMessage(bi, CHAN_X_FORBIDDEN, ci->name.c_str()); Log(LOG_COMMAND, "denied", bi) << "Access denied for user " << u->GetMask() << " with command " << command << " because of FORBIDDEN channel " << ci->name; return; } else if (ci->HasFlag(CI_SUSPENDED) && !c->HasFlag(CFLAG_ALLOW_SUSPENDED)) { - notice_lang(bi->nick, u, CHAN_X_FORBIDDEN, ci->name.c_str()); + u->SendMessage(bi, CHAN_X_FORBIDDEN, ci->name.c_str()); Log(LOG_COMMAND, "denied", bi) << "Access denied for user " << u->GetMask() << " with command " << command << " because of SUSPENDED channel " << ci->name; return; } } else if (!c->HasFlag(CFLAG_ALLOW_UNREGISTEREDCHANNEL)) { - notice_lang(bi->nick, u, CHAN_X_NOT_REGISTERED, params[0].c_str()); + u->SendMessage(bi, CHAN_X_NOT_REGISTERED, params[0].c_str()); return; } } /* A user not giving a channel name for a param that should be a channel */ else { - notice_lang(bi->nick, u, CHAN_X_INVALID, params[0].c_str()); + u->SendMessage(bi, CHAN_X_INVALID, params[0].c_str()); return; } } @@ -130,7 +129,7 @@ void mod_run_cmd(BotInfo *bi, User *u, Command *c, const Anope::string &command, // If the command requires a permission, and they aren't registered or don't have the required perm, DENIED if (!c->permission.empty() && !u->Account()->HasCommand(c->permission)) { - notice_lang(bi->nick, u, ACCESS_DENIED); + u->SendMessage(bi, ACCESS_DENIED); Log(LOG_COMMAND, "denied", bi) << "Access denied for user " << u->GetMask() << " with command " << command; return; } @@ -165,23 +164,23 @@ void mod_help_cmd(BotInfo *bi, User *u, const Anope::string &cmd) Anope::string subcommand = tokens.StreamEnd() ? "" : tokens.GetRemaining(); if (!c || (Config->HidePrivilegedCommands && !c->permission.empty() && (!u->Account() || !u->Account()->HasCommand(c->permission))) || !c->OnHelp(u, subcommand)) - notice_lang(bi->nick, u, NO_HELP_AVAILABLE, cmd.c_str()); + u->SendMessage(bi, NO_HELP_AVAILABLE, cmd.c_str()); else { u->SendMessage(bi->nick, " "); /* Inform the user what permission is required to use the command */ if (!c->permission.empty()) - notice_lang(bi->nick, u, COMMAND_REQUIRES_PERM, c->permission.c_str()); + u->SendMessage(bi, COMMAND_REQUIRES_PERM, c->permission.c_str()); /* User isn't identified and needs to be to use this command */ if (!c->HasFlag(CFLAG_ALLOW_UNREGISTERED) && !u->IsIdentified()) - notice_lang(bi->nick, u, COMMAND_IDENTIFY_REQUIRED); + u->SendMessage(bi, COMMAND_IDENTIFY_REQUIRED); /* User doesn't have the proper permission to use this command */ else if (!c->permission.empty() && (!u->Account() || !u->Account()->HasCommand(c->permission))) - notice_lang(bi->nick, u, COMMAND_CANNOT_USE); + u->SendMessage(bi, COMMAND_CANNOT_USE); /* User can use this command */ else - notice_lang(bi->nick, u, COMMAND_CAN_USE); + u->SendMessage(bi, COMMAND_CAN_USE); } } diff --git a/src/config.cpp b/src/config.cpp index 63141be0b..fda4d3881 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -101,9 +101,6 @@ ServerConfig::ServerConfig() : errstr(""), config_data() } } - if ((this->NSDefLanguage = langlist[this->NSDefLanguage]) < 0) - this->NSDefLanguage = DEF_LANGUAGE; - if (this->CSDefBantype < 0 || this->CSDefBantype > 3) { throw ConfigException("Value of CSDefBantype must be between 0 and 3 included"); @@ -530,15 +527,6 @@ bool ValidatePort(ServerConfig *, const Anope::string &tag, const Anope::string return true; } -bool ValidateLanguage(ServerConfig *, const Anope::string &, const Anope::string &, ValueItem &data) -{ - int language = data.GetInteger(); - if (language < 1 || language > USED_LANGS) - throw ConfigException("The value for <nickserv:defaultlanguage> must be between 1 and " + stringify(USED_LANGS) + "!"); - data.Set(--language); - return true; -} - bool ValidateGuestPrefix(ServerConfig *conf, const Anope::string &tag, const Anope::string &value, ValueItem &data) { ValidateNotEmpty(conf, tag, value, data); @@ -1059,7 +1047,8 @@ void ServerConfig::Read() {"nickserv", "modules", "", new ValueContainerString(&NickCoreModules), DT_STRING, NoValidation}, {"nickserv", "forceemail", "no", new ValueContainerBool(&this->NSForceEmail), DT_BOOLEAN, ValidateEmailReg}, {"nickserv", "defaults", "secure memosignon memoreceive", new ValueContainerString(&NSDefaults), DT_STRING, NoValidation}, - {"nickserv", "defaultlanguage", "0", new ValueContainerUInt(&this->NSDefLanguage), DT_UINTEGER, ValidateLanguage}, + {"nickserv", "languages", "", new ValueContainerString(&this->Languages), DT_STRING, NoValidation}, + {"nickserv", "defaultlanguage", "0", new ValueContainerString(&this->NSDefLanguage), DT_STRING, NoValidation}, {"nickserv", "regdelay", "0", new ValueContainerTime(&this->NSRegDelay), DT_TIME, NoValidation}, {"nickserv", "resenddelay", "0", new ValueContainerTime(&this->NSResendDelay), DT_TIME, NoValidation}, {"nickserv", "expire", "21d", new ValueContainerTime(&this->NSExpire), DT_TIME, NoValidation}, diff --git a/src/hostserv.cpp b/src/hostserv.cpp index 31ff713f8..e8f4686cb 100644 --- a/src/hostserv.cpp +++ b/src/hostserv.cpp @@ -11,7 +11,6 @@ #include "services.h" #include "modules.h" -#include "language.h" E void moduleAddHostServCmds(); @@ -170,8 +169,8 @@ void do_on_id(User *u) u->UpdateHost(); if (!na->hostinfo.GetIdent().empty()) - notice_lang(Config->s_HostServ, u, HOST_IDENT_ACTIVATED, na->hostinfo.GetIdent().c_str(), na->hostinfo.GetHost().c_str()); + u->SendMessage(HostServ, HOST_IDENT_ACTIVATED, na->hostinfo.GetIdent().c_str(), na->hostinfo.GetHost().c_str()); else - notice_lang(Config->s_HostServ, u, HOST_ACTIVATED, na->hostinfo.GetHost().c_str()); + u->SendMessage(HostServ, HOST_ACTIVATED, na->hostinfo.GetHost().c_str()); } } diff --git a/src/init.cpp b/src/init.cpp index d882f34be..544dcbd7c 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -431,8 +431,8 @@ void Init(int ac, char **av) signal(SIGINT, sighandler); /* Initialize multi-language support */ - lang_init(); - Log(LOG_DEBUG) << "Loaded languages"; + Log(LOG_DEBUG) << "Loading Languages..."; + InitLanguages(); /* Initialize subservices */ ns_init(); diff --git a/src/language.cpp b/src/language.cpp index 9d629f599..71dabcf46 100644 --- a/src/language.cpp +++ b/src/language.cpp @@ -1,353 +1,5421 @@ -/* Multi-language support. - * - * (C) 2003-2010 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - #include "services.h" -#include "language.h" - -/*************************************************************************/ - -/* The list of lists of messages. */ -char **langtexts[NUM_LANGS]; - -/* The list of names of languages. */ -char *langnames[NUM_LANGS]; - -/* Indexes of available languages: */ -int langlist[NUM_LANGS]; - -/* Order in which languages should be displayed: (alphabetical) */ -static int langorder[NUM_LANGS] = { - LANG_EN_US, /* English (US) */ - LANG_FR, /* French */ - LANG_DE, /* German */ - LANG_IT, /* Italian */ - LANG_JA_JIS, /* Japanese (JIS encoding) */ - LANG_JA_EUC, /* Japanese (EUC encoding) */ - LANG_JA_SJIS, /* Japanese (SJIS encoding) */ - LANG_PT, /* Portugese */ - LANG_ES, /* Spanish */ - LANG_TR, /* Turkish */ - LANG_CAT, /* Catalan */ - LANG_GR, /* Greek */ - LANG_NL, /* Dutch */ - LANG_RU, /* Russian */ - LANG_HUN, /* Hungarian */ - LANG_PL, /* Polish */ -}; - -/*************************************************************************/ - -/* Load a language file. */ -static int read_int32(int32 *ptr, FILE *f) -{ - int a = fgetc(f); - int b = fgetc(f); - int c = fgetc(f); - int d = fgetc(f); - if (a == EOF || b == EOF || c == EOF || d == EOF) - return -1; - *ptr = a << 24 | b << 16 | c << 8 | d; - return 0; -} - -static void load_lang(int index, const char *filename) -{ - char buf[256]; - FILE *f; - int32 num, i; - - Log(LOG_DEBUG) << "Loading language " << index << " from file `languages/" << filename << "'"; - snprintf(buf, sizeof(buf), "languages/%s", filename); -#ifndef _WIN32 - const char *mode = "r"; +#if HAVE_GETTEXT +# include <libintl.h> #else - const char *mode = "rb"; +# define gettext(x) x #endif - if (!(f = fopen(buf, mode))) - { - throw CoreException("Failed to load language " + stringify(index) + " (" + stringify(filename) + ")"); - } - else if (read_int32(&num, f) < 0) - { - Log() << "Failed to read number of strings for language " << index << "(" << filename << ")"; - return; - } - else if (num != NUM_STRINGS) - Log() << "Warning: Bad number of strings (" << num << " , wanted " << NUM_STRINGS << ") for language " << index << " (" << filename << ")"; - langtexts[index] = static_cast<char **>(scalloc(sizeof(char *), NUM_STRINGS)); - if (num > NUM_STRINGS) - num = NUM_STRINGS; - for (i = 0; i < num; ++i) - { - int32 pos, len; - fseek(f, i * 8 + 4, SEEK_SET); - if (read_int32(&pos, f) < 0 || read_int32(&len, f) < 0) - { - Log() << "Failed to read entry " << i << " in language " << index << " (" << filename << ") TOC"; - while (--i >= 0) - { - if (langtexts[index][i]) - free(langtexts[index][i]); // XXX - } - free(langtexts[index]); - langtexts[index] = NULL; - return; - } - if (!len) - langtexts[index][i] = NULL; - else if (len >= 65536) - { - Log() << "Entry " << i << " in language " << index << " (" << filename << ") is too long (over 64k) -- corrupt TOC?"; - while (--i >= 0) - { - if (langtexts[index][i]) - free(langtexts[index][i]); // XXX - } - free(langtexts[index]); - langtexts[index] = NULL; - return; - } - else if (len < 0) - { - Log() << "Entry " << i << " in language " << index << " (" << filename << ") has negative length -- corrupt TOC?"; - while (--i >= 0) - { - if (langtexts[index][i]) - free(langtexts[index][i]); // XXX - } - free(langtexts[index]); - langtexts[index] = NULL; - return; - } - else - { - langtexts[index][i] = static_cast<char *>(malloc(len + 1)); - fseek(f, pos, SEEK_SET); - if (fread(langtexts[index][i], 1, len, f) != len) - { - Log() << "Failed to read string " << i << " in language " << index << "(" << filename << ")"; - while (--i >= 0) - { - if (langtexts[index][i]) - free(langtexts[index][i]); - } - free(langtexts[index]); - langtexts[index] = NULL; - return; - } - langtexts[index][i][len] = 0; - } - } - fclose(f); -} -/*************************************************************************/ +std::vector<Anope::string> languages; -/* Replace all %M's with "/msg " or "/" */ -void lang_sanitize() +void InitLanguages() { - int i = 0, j = 0; - int len = 0; - char tmp[2000]; - char *newstr = NULL; - for (i = 0; i < NUM_LANGS; ++i) +#if HAVE_GETTEXT + languages.clear(); + spacesepstream sep(Config->Languages); + Anope::string language; + + while (sep.GetToken(language)) { - for (j = 0; j < NUM_STRINGS; ++j) + if (!IsFile("languages/" + language + "/LC_MESSAGES/anope.mo")) { - if (strstr(langtexts[i][j], "%R")) - { - len = strlen(langtexts[i][j]); - strscpy(tmp, langtexts[i][j], sizeof(tmp)); - if (Config->UseStrictPrivMsg) - strnrepl(tmp, sizeof(tmp), "%R", "/"); - else - strnrepl(tmp, sizeof(tmp), "%R", "/msg "); - newstr = strdup(tmp); - free(langtexts[i][j]); // XXX - langtexts[i][j] = newstr; - } + Log() << "Error loading language " << language << ", file does not exist!"; } - } -} - - -/* Initialize list of lists. */ - -void lang_init() -{ - int i, j, n = 0; - - load_lang(LANG_CAT, "cat"); - load_lang(LANG_DE, "de"); - load_lang(LANG_EN_US, "en_us"); - load_lang(LANG_ES, "es"); - load_lang(LANG_FR, "fr"); - load_lang(LANG_GR, "gr"); - load_lang(LANG_PT, "pt"); - load_lang(LANG_TR, "tr"); - load_lang(LANG_IT, "it"); - load_lang(LANG_NL, "nl"); - load_lang(LANG_RU, "ru"); - load_lang(LANG_HUN, "hun"); - load_lang(LANG_PL, "pl"); - - for (i = 0; i < NUM_LANGS; ++i) - { - if (langtexts[langorder[i]] != NULL) + else { - langnames[langorder[i]] = langtexts[langorder[i]][LANG_NAME]; - langlist[n++] = langorder[i]; - for (j = 0; j < NUM_STRINGS; ++j) - { - if (!langtexts[langorder[i]][j]) - langtexts[langorder[i]][j] = langtexts[DEF_LANGUAGE][j]; - if (!langtexts[langorder[i]][j]) - langtexts[langorder[i]][j] = langtexts[LANG_EN_US][j]; - } + Log(LOG_DEBUG) << "Found language file " << language; + languages.push_back(language); } } - while (n < NUM_LANGS) - langlist[n++] = -1; - - /* Not what I intended to do, but these services are so archaïc - * that it's difficult to do more. */ - if ((Config->NSDefLanguage = langlist[Config->NSDefLanguage]) < 0) - Config->NSDefLanguage = DEF_LANGUAGE; - if (!langtexts[DEF_LANGUAGE]) - throw CoreException("Unable to load default language"); - for (i = 0; i < NUM_LANGS; ++i) + if (!bindtextdomain("anope", (services_dir + "/languages/").c_str())) { - if (!langtexts[i]) - langtexts[i] = langtexts[DEF_LANGUAGE]; + Log() << "Error calling bindtextdomain, " << Anope::LastError(); } - lang_sanitize(); +#else + Log() << "Can not load languages, gettext is not installed"; +#endif } -/*************************************************************************/ -/*************************************************************************/ - -/* Format a string in a strftime()-like way, but heed the user's language - * setting for month and day names. The string stored in the buffer will - * always be null-terminated, even if the actual string was longer than the - * buffer size. - * Assumption: No month or day name has a length (including trailing null) - * greater than BUFSIZE. - */ - -int strftime_lang(char *buf, int size, User *u, int format, struct tm *tm) +const Anope::string GetString(Anope::string language, LanguageString string) { - int language = u && u->Account() ? u->Account()->language : Config->NSDefLanguage; - char tmpbuf[BUFSIZE], buf2[BUFSIZE]; - char *s; - int i, ret; +#if HAVE_GETTEXT + /* For older databases */ + if (language == "en") + language.clear(); - if (!tm) - return 0; + /* Apply def language */ + if (language.empty() && !Config->NSDefLanguage.empty()) + language = Config->NSDefLanguage; - strscpy(tmpbuf, langtexts[language][format], sizeof(tmpbuf)); - if ((s = langtexts[language][STRFTIME_DAYS_SHORT])) - { - for (i = 0; i < tm->tm_wday; ++i) - s += strcspn(s, "\n") + 1; - i = strcspn(s, "\n"); - strncpy(buf2, s, i); - buf2[i] = 0; - strnrepl(tmpbuf, sizeof(tmpbuf), "%a", buf2); - } - if ((s = langtexts[language][STRFTIME_DAYS_LONG])) - { - for (i = 0; i < tm->tm_wday; ++i) - s += strcspn(s, "\n") + 1; - i = strcspn(s, "\n"); - strncpy(buf2, s, i); - buf2[i] = 0; - strnrepl(tmpbuf, sizeof(tmpbuf), "%A", buf2); - } - if ((s = langtexts[language][STRFTIME_MONTHS_SHORT])) - { - for (i = 0; i < tm->tm_mon; ++i) - s += strcspn(s, "\n") + 1; - i = strcspn(s, "\n"); - strncpy(buf2, s, i); - buf2[i] = 0; - strnrepl(tmpbuf, sizeof(tmpbuf), "%b", buf2); - } - if ((s = langtexts[language][STRFTIME_MONTHS_LONG])) - { - for (i = 0; i < tm->tm_mon; ++i) - s += strcspn(s, "\n") + 1; - i = strcspn(s, "\n"); - strncpy(buf2, s, i); - buf2[i] = 0; - strnrepl(tmpbuf, sizeof(tmpbuf), "%B", buf2); - } - ret = strftime(buf, size, tmpbuf, tm); - if (ret == size) - buf[size - 1] = 0; - return ret; -} - -/*************************************************************************/ -/*************************************************************************/ - -/* Send a syntax-error message to the user. */ - -void syntax_error(const Anope::string &service, User *u, const Anope::string &command, int msgnum) -{ - const char *str; + if (language.empty()) +#endif + return language_strings[string]; - if (!u) - return; +#if HAVE_GETTEXT + setlocale(LC_ALL, language.c_str()); + const char *ret = dgettext("anope", language_strings[string].c_str()); + setlocale(LC_ALL, ""); - str = getstring(u, msgnum); - notice_lang(service, u, SYNTAX_ERROR, str); - notice_lang(service, u, MORE_INFO, service.c_str(), command.c_str()); + return ret ? ret : ""; +#endif } -const char *getstring(NickAlias *na, int index) +const Anope::string GetString(LanguageString string) { - // Default to config - int langidx = Config->NSDefLanguage; - - // If they are registered (na->nc), and NOT forbidden - if (na && na->nc && !na->HasFlag(NS_FORBIDDEN)) - langidx = na->nc->language; // set language to their nickcore's language - - return langtexts[langidx][index]; + return GetString("", string); } -const char *getstring(const NickCore *nc, int index) +const Anope::string GetString(const NickCore *nc, LanguageString string) { - // Default to config - int langidx = Config->NSDefLanguage; - - if (nc) - langidx = nc->language; - - return langtexts[langidx][index]; + return GetString(nc ? nc->language : "", string); } -const char *getstring(const User *u, int index) +const Anope::string GetString(const User *u, LanguageString string) { - return getstring(u->Account(), index); + if (!u) + return GetString(string); + const NickCore *nc = u->Account(); + NickAlias *na = NULL; + if (!nc) + na = findnick(u->nick); + return GetString(nc ? nc : (na ? na->nc : NULL), string); } -const char *getstring(int index) +void SyntaxError(BotInfo *bi, User *u, const Anope::string &command, LanguageString message) { - // Default to config - int langidx = Config->NSDefLanguage; + if (!bi || !u || command.empty()) + return; - return langtexts[langidx][index]; + Anope::string str = GetString(u, message); + u->SendMessage(bi, SYNTAX_ERROR, str.c_str()); + u->SendMessage(bi, MORE_INFO, bi->nick.c_str(), command.c_str()); } -/*************************************************************************/ +Anope::string language_strings[LANG_STRING_COUNT] = { + /* LANG_NAME */ + gettext("English"), + /* COMMAND_REQUIRES_PERM */ + gettext("Access to this command requires the permission %s to be present in your opertype."), + /* COMMAND_IDENTIFY_REQUIRED */ + gettext("You need to be identified to use this command."), + /* COMMAND_CANNOT_USE */ + gettext("You cannot use this command."), + /* COMMAND_CAN_USE */ + gettext("You can use this command."), + /* USER_RECORD_NOT_FOUND */ + gettext("Internal error - unable to process request."), + /* UNKNOWN_COMMAND */ + gettext("Unknown command %s."), + /* UNKNOWN_COMMAND_HELP */ + gettext("Unknown command %s. \"%R%s HELP\" for help."), + /* SYNTAX_ERROR */ + gettext("Syntax: %s"), + /* MORE_INFO */ + gettext("%R%s HELP %s for more information."), + /* NO_HELP_AVAILABLE */ + gettext("No help available for %s."), + /* OBSOLETE_COMMAND */ + gettext("This command is obsolete; use %s instead."), + /* BAD_USERHOST_MASK */ + gettext("Mask must be in the form user@host."), + /* BAD_EXPIRY_TIME */ + gettext("Invalid expiry time."), + /* USERHOST_MASK_TOO_WIDE */ + gettext("%s coverage is too wide; Please use a more specific mask."), + /* SERVICE_OFFLINE */ + gettext("%s is currently offline."), + /* READ_ONLY_MODE */ + gettext("Notice: Services is in read-only mode; changes will not be saved!"), + /* PASSWORD_INCORRECT */ + gettext("Password incorrect."), + /* INVALID_TARGET */ + gettext("\"/msg %s\" is no longer supported. Use \"/msg %s@%s\" or \"/%s\" instead."), + /* ACCESS_DENIED */ + gettext("Access denied."), + /* MORE_OBSCURE_PASSWORD */ + gettext("Please try again with a more obscure password. Passwords should be at least five characters long, should not be something easily guessed (e.g. your real name or your nick), and cannot contain the space or tab characters."), + /* PASSWORD_TOO_LONG */ + gettext("Your password is too long. Please try again with a shorter password."), + /* NICK_NOT_REGISTERED */ + gettext("Your nick isn't registered."), + /* NICK_NOT_REGISTERED_HELP */ + gettext("Your nick isn't registered. Type %R%s HELP for information on registering your nickname."), + /* NICK_X_IS_SERVICES */ + gettext("Nick %s is part of this Network's Services."), + /* NICK_X_NOT_REGISTERED */ + gettext("Nick %s isn't registered."), + /* NICK_X_IN_USE */ + gettext("Nick %s is currently in use."), + /* NICK_X_NOT_IN_USE */ + gettext("Nick %s isn't currently in use."), + /* NICK_X_NOT_ON_CHAN */ + gettext("%s is not currently on channel %s."), + /* NICK_X_FORBIDDEN */ + gettext("Nick %s may not be registered or used."), + /* NICK_X_FORBIDDEN_OPER */ + gettext("Nick %s has been forbidden by %s:\n" + "%s"), + /* NICK_X_ILLEGAL */ + gettext("Nick %s is an illegal nickname and cannot be used."), + /* NICK_X_TRUNCATED */ + gettext("Nick %s was truncated to %d characters."), + /* NICK_X_SUSPENDED */ + gettext("Nick %s is currently suspended."), + /* CHAN_X_NOT_REGISTERED */ + gettext("Channel %s isn't registered."), + /* CHAN_X_NOT_IN_USE */ + gettext("Channel %s doesn't exist."), + /* CHAN_X_FORBIDDEN */ + gettext("Channel %s may not be registered or used."), + /* CHAN_X_FORBIDDEN_OPER */ + gettext("Channel %s has been forbidden by %s:\n" + "%s"), + /* CHAN_X_SUSPENDED */ + gettext(" Suspended: [%s] %s"), + /* NICK_IDENTIFY_REQUIRED */ + gettext("Password authentication required for that command.\n" + "Retry after typing %R%s IDENTIFY password."), + /* CHAN_IDENTIFY_REQUIRED */ + gettext("Password authentication required for that command.\n" + "Retry after typing %R%s IDENTIFY %s password."), + /* MAIL_DISABLED */ + gettext("Services have been configured to not send mail."), + /* MAIL_INVALID */ + gettext("E-mail for %s is invalid."), + /* MAIL_X_INVALID */ + gettext("%s is not a valid e-mail address."), + /* MAIL_LATER */ + gettext("Cannot send mail now; please retry a little later."), + /* MAIL_DELAYED */ + gettext("Please wait %d seconds and retry."), + /* NO_REASON */ + gettext("No reason"), + /* UNKNOWN */ + gettext("<unknown>"), + /* DURATION_DAY */ + gettext("1 day"), + /* DURATION_DAYS */ + gettext("%d days"), + /* DURATION_HOUR */ + gettext("1 hour"), + /* DURATION_HOURS */ + gettext("%d hours"), + /* DURATION_MINUTE */ + gettext("1 minute"), + /* DURATION_MINUTES */ + gettext("%d minutes"), + /* DURATION_SECOND */ + gettext("1 second"), + /* DURATION_SECONDS */ + gettext("%d seconds"), + /* NO_EXPIRE */ + gettext("does not expire"), + /* EXPIRES_SOON */ + gettext("expires at next database update"), + /* EXPIRES_M */ + gettext("expires in %d minutes"), + /* EXPIRES_1M */ + gettext("expires in %d minute"), + /* EXPIRES_HM */ + gettext("expires in %d hours, %d minutes"), + /* EXPIRES_H1M */ + gettext("expires in %d hours, %d minute"), + /* EXPIRES_1HM */ + gettext("expires in %d hour, %d minutes"), + /* EXPIRES_1H1M */ + gettext("expires in %d hour, %d minute"), + /* EXPIRES_D */ + gettext("expires in %d days"), + /* EXPIRES_1D */ + gettext("expires in %d day"), + /* END_OF_ANY_LIST */ + gettext("E |
