summaryrefslogtreecommitdiff
path: root/src/language.cpp
diff options
context:
space:
mode:
authorAdam <Adam@Anope.org>2010-05-25 00:57:25 -0500
committerAdam <Adam@anope.org>2010-06-18 21:04:07 -0400
commit4a2b9ebcf38d6c0a2860b966421b3af125438488 (patch)
treee4af4e59fd29352138db0fb0ff614d50233850b8 /src/language.cpp
parent2fba686904e6f78ebab35df171c5757afeebf05d (diff)
Renamed all of source files from .c to .cpp
Diffstat (limited to 'src/language.cpp')
-rw-r--r--src/language.cpp339
1 files changed, 339 insertions, 0 deletions
diff --git a/src/language.cpp b/src/language.cpp
new file mode 100644
index 000000000..3f5c900e9
--- /dev/null
+++ b/src/language.cpp
@@ -0,0 +1,339 @@
+/* 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;
+
+ Alog(LOG_DEBUG) << "Loading language " << index << " from file `languages/" << filename << "'";
+ snprintf(buf, sizeof(buf), "languages/%s", filename);
+#ifndef _WIN32
+ if (!(f = fopen(buf, "r"))) {
+#else
+ if (!(f = fopen(buf, "rb"))) {
+#endif
+ log_perror("Failed to load language %d (%s)", index, filename);
+ return;
+ } else if (read_int32(&num, f) < 0) {
+ Alog() << "Failed to read number of strings for language " << index << "(" << filename << ")";
+ return;
+ } else if (num != NUM_STRINGS) {
+ Alog() << "Warning: Bad number of strings (" << num << " , wanted " << NUM_STRINGS << ") "
+ << "for language " << index << " (" << filename << ")";
+ }
+ langtexts[index] = new 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) {
+ Alog() << "Failed to read entry " << i << " in language " << index << " (" << filename << ") TOC";
+ while (--i >= 0)
+ {
+ if (langtexts[index][i])
+ delete [] langtexts[index][i];
+ }
+ delete [] langtexts[index];
+ langtexts[index] = NULL;
+ return;
+ }
+ if (len == 0) {
+ langtexts[index][i] = NULL;
+ } else if (len >= 65536) {
+ Alog() << "Entry " << i << " in language " << index << " (" << filename << ") is too long (over 64k) -- corrupt TOC?";
+ while (--i >= 0) {
+ if (langtexts[index][i])
+ delete [] langtexts[index][i];
+ }
+ delete [] langtexts[index];
+ langtexts[index] = NULL;
+ return;
+ } else if (len < 0) {
+ Alog() << "Entry " << i << " in language " << index << " (" << filename << ") has negative length -- corrupt TOC?";
+ while (--i >= 0) {
+ if (langtexts[index][i])
+ delete [] langtexts[index][i];
+ }
+ delete [] langtexts[index];
+ langtexts[index] = NULL;
+ return;
+ } else {
+ langtexts[index][i] = new char[len + 1];
+ fseek(f, pos, SEEK_SET);
+ if (fread(langtexts[index][i], 1, len, f) != len) {
+ Alog() << "Failed to read string " << i << " in language " << index << "(" << filename << ")";
+ while (--i >= 0) {
+ if (langtexts[index][i])
+ delete [] langtexts[index][i];
+ }
+ delete [] langtexts[index];
+ langtexts[index] = NULL;
+ return;
+ }
+ langtexts[index][i][len] = 0;
+ }
+ }
+ fclose(f);
+}
+
+/*************************************************************************/
+
+/* Replace all %M's with "/msg " or "/" */
+void lang_sanitize()
+{
+ int i = 0, j = 0;
+ int len = 0;
+ char tmp[2000];
+ char *newstr = NULL;
+ for (i = 0; i < NUM_LANGS; i++) {
+ for (j = 0; j < NUM_STRINGS; j++) {
+ 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 = sstrdup(tmp);
+ delete [] langtexts[i][j];
+ langtexts[i][j] = newstr;
+ }
+ }
+ }
+}
+
+
+/* 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) {
+ 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];
+ }
+ }
+ }
+ }
+ 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])
+ fatal("Unable to load default language");
+ for (i = 0; i < NUM_LANGS; i++) {
+ if (!langtexts[i])
+ langtexts[i] = langtexts[DEF_LANGUAGE];
+ }
+ lang_sanitize();
+}
+
+/*************************************************************************/
+/*************************************************************************/
+
+/* 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)
+{
+ int language = u && u->Account() ? u->Account()->language : Config.NSDefLanguage;
+ char tmpbuf[BUFSIZE], buf2[BUFSIZE];
+ char *s;
+ int i, ret;
+
+ if (!tm) {
+ return 0;
+ }
+
+ strscpy(tmpbuf, langtexts[language][format], sizeof(tmpbuf));
+ if ((s = langtexts[language][STRFTIME_DAYS_SHORT]) != NULL) {
+ 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]) != NULL) {
+ 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]) != NULL) {
+ 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]) != NULL) {
+ 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(char *service, User * u, const char *command, int msgnum)
+{
+ const char *str;
+
+ if (!u) {
+ return;
+ }
+
+ str = getstring(u, msgnum);
+ notice_lang(service, u, SYNTAX_ERROR, str);
+ notice_lang(service, u, MORE_INFO, service, command);
+}
+
+const char *getstring(NickAlias *na, int index)
+{
+ // 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];
+}
+
+const char *getstring(NickCore *nc, int index)
+{
+ // Default to config
+ int langidx = Config.NSDefLanguage;
+
+ if (nc)
+ {
+ langidx = nc->language;
+ }
+
+ return langtexts[langidx][index];
+}
+
+const char *getstring(User *u, int index)
+{
+ return getstring(u->Account(), index);
+}
+
+const char *getstring(int index)
+{
+ // Default to config
+ int langidx = Config.NSDefLanguage;
+
+ return langtexts[langidx][index];
+}
+
+/*************************************************************************/