Crossfire Server, Trunk
languages.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
14 #include "global.h"
15 
16 #include <errno.h>
17 #include <stdlib.h>
18 #include <string.h>
19 
23 typedef struct i18n_message {
26 } i18n_message;
27 
31 typedef struct i18n_file {
34  int count;
36 } i18n_file;
37 
39 static int i18n_count = 0;
41 static struct i18n_file *i18n_files = NULL;
43 static int i18n_default = -1;
44 
46  return strcmp(a->code, b->code);
47 }
48 
55 const char *i18n(const object *who, const char *code) {
56  i18n_message search, *found;
57 
58  if (!who || !who->contr)
59  return code;
60 
61  if (who->contr->language < 0 || who->contr->language >= i18n_count)
62  return code;
63 
64  search.code = add_string(code);
65 
66  found = bsearch(&search, i18n_files[who->contr->language].messages, i18n_files[who->contr->language].count, sizeof(i18n_message), (int (*)(const void *, const void *))i18n_message_compare_code);
67 
68  free_string(search.code);
69 
70  if (found)
71  return found->message;
72 
73  return code;
74 }
75 
81 int i18n_find_language_by_code(const char *code) {
82  int index;
83  for (index = 0; index < i18n_count; index++) {
84  if (strcmp(code, i18n_files[index].code) == 0)
85  return index;
86  }
87 
88  return -1;
89 }
90 
96 int i18n_get_language_by_code(const char *code) {
98  if (try != -1)
99  return try;
100  return i18n_default;
101 }
102 
109  if (language < 0 || language >= i18n_count)
110  return i18n_files[i18n_default].code;
111  return i18n_files[language].code;
112 }
113 
118 void i18n_list_languages(object *who) {
119  int index;
120  for (index = 0; index < i18n_count; index++) {
122  "[fixed]%s: %s",
125  );
126  }
127 }
128 
137 static void convert_newline(char *line) {
138  char *next;
139  char buf[MAX_BUF];
140 
141  while ((next = strstr(line, "\\n")) != NULL) {
142  *next = '\n';
143  *(next+1) = '\0';
144  snprintf(buf, MAX_BUF, "%s%s", line, next+2);
145  strcpy(line, buf);
146  }
147 }
148 
154 void i18n_init(void) {
155  char dirname[MAX_BUF], filename[MAX_BUF*2], *line;
156  BufferReader *br;
157  char *token;
158  DIR *dir;
159  struct dirent *file;
160  i18n_message code, *found;
161 
162  snprintf(dirname, sizeof(dirname), "%s/i18n/", settings.datadir);
163 
164  dir = opendir(dirname);
165  if (dir == NULL) {
166  LOG(llevError, "i18n: couldn't open %s\n", dirname);
168  }
169 
170  code.code = add_string("LN");
171 
172  while ((file = readdir(dir)) != NULL) {
173  if (strncmp(file->d_name, "messages.", 9) != 0)
174  continue;
175 
176  snprintf(filename, sizeof(filename), "%s%s", dirname, file->d_name);
177  br = bufferreader_init_from_file(NULL, filename, "i18n: couldn't open %s: %s\n", llevError);
178  if (!br) {
180  }
181 
182  i18n_files = realloc(i18n_files, (i18n_count + 1) * sizeof(i18n_file));
183  if (!i18n_files) {
184  LOG(llevError, "i18n: couldn't allocate memory!\n");
186  }
187  i18n_files[i18n_count].code = add_string(file->d_name + 9);
190 
191  while ((line = bufferreader_next_line(br)) != NULL) {
192  if (line[0] != '#' && line[0] != '\0') {
194 
195  token = strtok(line, "|");
198  token = strtok(NULL, "|");
199  if (token != NULL) {
202  } else {
204  }
206  }
207  }
209 
210  qsort(i18n_files[i18n_count].messages, i18n_files[i18n_count].count, sizeof(i18n_message), (int (*)(const void *, const void *))i18n_message_compare_code);
211  found = bsearch(&code, i18n_files[i18n_count].messages, i18n_files[i18n_count].count, sizeof(i18n_message), (int (*)(const void *, const void *))i18n_message_compare_code);
212  if (found == NULL) {
213  LOG(llevError, "i18n: no language set in %s\n", filename);
215  }
216 
217  i18n_files[i18n_count].name = found->message;
218  LOG(llevDebug, "i18n: %d strings for %s\n",
219  i18n_files[i18n_count].count, found->message);
220 
221  if (strcmp(i18n_files[i18n_count].code, "en") == 0)
223 
224  i18n_count++;
225  }
226  closedir(dir);
227 
228  free_string(code.code);
229 
230  if (i18n_default == -1) {
231  LOG(llevError, "i18n: couldn't find default language (en)\n");
233  }
234 }
235 
239 void i18n_free(void) {
240  int file, message;
241 
242  for (file = 0; file < i18n_count; file++) {
243  free_string(i18n_files[file].code); /* name is a copy of a message */
244  for (message = 0; message < i18n_files[file].count; message++) {
247  }
248  free(i18n_files[file].messages);
249  }
250  free(i18n_files);
251  i18n_files = NULL;
252  i18n_count = 0;
253 }
give.next
def next
Definition: give.py:44
global.h
add_refcount
sstring add_refcount(sstring str)
Definition: shstr.c:210
add_string
sstring add_string(const char *str)
Definition: shstr.c:124
llevError
@ llevError
Definition: logger.h:11
i18n_message
struct i18n_message i18n_message
token
Definition: token.py:1
convert_newline
static void convert_newline(char *line)
Definition: languages.c:137
bufferreader_init_from_file
BufferReader * bufferreader_init_from_file(BufferReader *br, const char *filepath, const char *failureMessage, LogLevel failureLevel)
Definition: bufferreader.c:65
i18n_message_compare_code
static int i18n_message_compare_code(const i18n_message *a, const i18n_message *b)
Definition: languages.c:45
i18n_find_language_by_code
int i18n_find_language_by_code(const char *code)
Definition: languages.c:81
Settings::datadir
const char * datadir
Definition: global.h:243
disinfect.a
a
Definition: disinfect.py:13
mad_mage_user.file
file
Definition: mad_mage_user.py:15
i18n_message
Definition: languages.c:23
i18n_file::name
sstring name
Definition: languages.c:33
bufferreader_next_line
char * bufferreader_next_line(BufferReader *br)
Definition: bufferreader.c:102
SEE_LAST_ERROR
@ SEE_LAST_ERROR
Definition: define.h:52
npc_dialog.filename
filename
Definition: npc_dialog.py:99
MSG_TYPE_COMMAND
#define MSG_TYPE_COMMAND
Definition: newclient.h:404
settings
struct Settings settings
Definition: init.c:39
free_string
void free_string(sstring str)
Definition: shstr.c:280
autojail.who
who
Definition: autojail.py:3
opendir
DIR * opendir(const char *)
is_valid_types_gen.line
line
Definition: is_valid_types_gen.py:34
i18n_file::count
int count
Definition: languages.c:34
fatal
void fatal(enum fatal_error err)
Definition: utils.c:580
readdir
struct dirent * readdir(DIR *)
i18n_get_language_code
sstring i18n_get_language_code(int language)
Definition: languages.c:108
Ice.b
b
Definition: Ice.py:48
i18n_file
Definition: languages.c:31
sstring
const typedef char * sstring
Definition: global.h:40
disinfect.count
int count
Definition: disinfect.py:7
MSG_SUBTYPE_NONE
#define MSG_SUBTYPE_NONE
Definition: newclient.h:420
i18n_get_language_by_code
int i18n_get_language_by_code(const char *code)
Definition: languages.c:96
MAX_BUF
#define MAX_BUF
Definition: define.h:35
navar-midane_apply.messages
list messages
Definition: navar-midane_apply.py:8
i18n_files
static struct i18n_file * i18n_files
Definition: languages.c:41
is_valid_types_gen.found
found
Definition: is_valid_types_gen.py:39
diamondslots.message
string message
Definition: diamondslots.py:57
i18n_count
static int i18n_count
Definition: languages.c:39
dirent
#define dirent
Definition: xdir.h:12
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:262
i18n_list_languages
void i18n_list_languages(object *who)
Definition: languages.c:118
i18n_init
void i18n_init(void)
Definition: languages.c:154
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
i18n_file::code
sstring code
Definition: languages.c:32
bufferreader_destroy
void bufferreader_destroy(BufferReader *br)
Definition: bufferreader.c:40
i18n_message::message
sstring message
Definition: languages.c:25
npc_dialog.index
int index
Definition: npc_dialog.py:102
buf
StringBuffer * buf
Definition: readable.c:1610
i18n_file::messages
struct i18n_message * messages
Definition: languages.c:35
make_face_from_files.int
int
Definition: make_face_from_files.py:26
i18n_default
static int i18n_default
Definition: languages.c:43
i18n
const char * i18n(const object *who, const char *code)
Definition: languages.c:55
i18n_file
struct i18n_file i18n_file
closedir
int closedir(DIR *)
OUT_OF_MEMORY
@ OUT_OF_MEMORY
Definition: define.h:48
BufferReader
Definition: bufferreader.c:21
i18n_message::code
sstring code
Definition: languages.c:24
draw_ext_info_format
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Definition: main.c:319
i18n_free
void i18n_free(void)
Definition: languages.c:239
llevDebug
@ llevDebug
Definition: logger.h:13
give.name
name
Definition: give.py:27