load all languages on startup
[NeonServV5.git] / lang.c
1 #include "lang.h"
2 #include "UserNode.h"
3 #include "DBHelper.h"
4 #include "mysqlConn.h"
5
6 #define DEFAULT_LANG_TAG "EN"
7 #define DEFAULT_LANG_NAME "English"
8
9 static struct language **langdict;
10 static struct language *lang_c;
11
12 void init_lang() {
13     langdict = calloc(MAXLANGUAGES, sizeof(*langdict));
14 }
15
16 void free_lang() {
17     
18 }
19
20 void load_languages() {
21     MYSQL_RES *res;
22     MYSQL_ROW row;
23     printf_mysql_query("SELECT `lang`, `text` FROM `language` WHERE `ident` = 'name'");
24     res = mysql_use();
25     while((row = mysql_fetch_row(res)) != NULL) {
26         load_language(row[0], row[1]);
27     }
28 }
29
30 static struct language* add_language(char *langtag, char *langname) {
31     int cindex;
32     for(cindex = 0; cindex < MAXLANGUAGES; cindex++) {
33         if(langdict[cindex] == NULL) break;
34         if(!strcmp(langdict[cindex]->langname, langname) || !strcmp(langdict[cindex]->langtag, langtag))
35             return langdict[cindex];
36     }
37     if(cindex == MAXLANGUAGES) return NULL;
38     struct language *lang = malloc(sizeof(*lang));
39     if (!lang) {
40         perror("malloc() failed");
41         return NULL;
42     }
43     lang->langtag = strdup(langtag);
44     lang->langname = strdup(langname);
45     struct language_table **entrys = calloc(27, sizeof(*entrys));
46     lang->entrys = entrys;
47     return lang;
48 }
49
50 static int get_entry_index(const char *ident) {
51     const char *underscore = strstr(ident, "_");
52     if(!underscore || !(underscore[1] >= 65 && underscore[1] <= 90)) return 26;
53     return (underscore[1] - 'A');
54 }
55
56 void load_language(char *tag, char *name) {
57     struct language *lang = get_language_by_tag(tag);
58     if(lang == get_default_language()) return;
59     if(lang) {
60         //remove all entrys
61         int cindex;
62         struct language_table *entry, *next;
63         for(cindex = 0; cindex < 27; cindex++) {
64             for(entry = lang->entrys[cindex]; entry; entry = next) {
65                 next = entry->next;
66                 free(entry->ident);
67                 free(entry->text);
68                 free(entry);
69             }
70             lang->entrys[cindex] = NULL;
71         }
72     } else
73         lang = add_language(tag, name);
74     if(!lang) return;
75     MYSQL_RES *res;
76     MYSQL_ROW row;
77     printf_mysql_query("SELECT `ident`, `text` FROM `language` WHERE `lang` = '%s' AND `ident` != 'name'", escape_string(tag));
78     res = mysql_use();
79     while((row = mysql_fetch_row(res)) != NULL) {
80         register_language_string(lang, row[0], row[1]);
81     }
82 }
83
84 struct language* get_language_by_tag(char *tag) {
85     int cindex;
86     for(cindex = 0; cindex < MAXLANGUAGES; cindex++) {
87         if(langdict[cindex] == NULL) break;
88         if(!strcmp(langdict[cindex]->langtag, tag))
89             return langdict[cindex];
90     }
91     return NULL;
92 }
93
94 struct language* get_language_by_name(char *name) {
95     int cindex;
96     for(cindex = 0; cindex < MAXLANGUAGES; cindex++) {
97         if(langdict[cindex] == NULL) break;
98         if(!strcmp(langdict[cindex]->langname, name))
99             return langdict[cindex];
100     }
101     return NULL;
102 }
103
104 struct language* get_default_language() {
105     if(lang_c == NULL) 
106         lang_c = add_language(DEFAULT_LANG_TAG, DEFAULT_LANG_NAME);
107     return lang_c;
108 }
109
110 void register_default_language_table(const struct default_language_entry *msgtab) {
111     if(lang_c == NULL) 
112         lang_c = add_language(DEFAULT_LANG_TAG, DEFAULT_LANG_NAME);
113     struct language_table *lang_entry;
114     int cindex;
115     while(msgtab->ident) {
116         cindex = get_entry_index(msgtab->ident);
117         lang_entry = malloc(sizeof(*lang_entry));
118         if (!lang_entry) {
119             perror("malloc() failed");
120             return;
121         }
122         lang_entry->ident = strdup(msgtab->ident);
123         lang_entry->text = strdup(msgtab->text);
124         lang_entry->next = lang_c->entrys[cindex];
125         lang_c->entrys[cindex] = lang_entry;
126         msgtab++;
127     }
128 }
129
130 void register_language_string(struct language *lang, char *ident, char *text) {
131     int cindex = get_entry_index(ident);
132     struct language_table *lang_entry = malloc(sizeof(*lang_entry));
133     if (!lang_entry) {
134         perror("malloc() failed");
135         return;
136     }
137     lang_entry->ident = strdup(ident);
138     lang_entry->text = strdup(text);
139     lang_entry->next = lang->entrys[cindex];
140     lang->entrys[cindex] = lang_entry;
141 }
142
143 char *get_language_string(struct UserNode *user, const char* msg_ident) {
144     struct language* lang;
145     if((user->flags & USERFLAG_ISAUTHED)) {
146         loadUserSettings(user);
147         lang = user->language;
148     } else
149         lang = lang_c;
150     int cindex = get_entry_index(msg_ident);
151     struct language_table* entry;
152     for(entry = lang->entrys[cindex]; entry; entry = entry->next) {
153         if(!strcmp(entry->ident, msg_ident))
154             return entry->text;
155     }
156     return NULL;
157 }
158
159 char *build_language_string(struct UserNode *user, char *buffer, const char *msg_ident, ...) {
160     char *formatStr = get_language_string(user, msg_ident);
161     if(!formatStr) return NULL;
162     if(buffer == NULL) {
163         buffer = (char *)malloc((MAXLEN+1) * sizeof(char));
164         if (!buffer) {
165             perror("malloc() failed");
166             return NULL;
167         }
168     }
169     int pos;
170     va_list arg_list;
171     buffer[0] = '\0';
172     va_start(arg_list, msg_ident);
173     pos = vsnprintf(buffer, MAXLEN - 2, formatStr, arg_list);
174     va_end(arg_list);
175     if (pos < 0 || pos > (MAXLEN - 2)) pos = MAXLEN - 2;
176     buffer[pos] = '\0';
177     return buffer;
178 }