Crossfire Server, Trunk
languages.cpp
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 #include <map>
20 #include <memory>
21 
25 struct i18n_file {
28  std::map<sstring, sstring> messages;
29 };
30 
32 static std::vector<i18n_file *> i18n_files;
34 static i18n_file *i18n_default = nullptr;
35 
42 const char *i18n(const object *who, const char *code) {
43  if (!who || !who->contr || !who->contr->language)
44  return code;
45 
46  sstring scode = add_string(code);
47  i18n_file *file = static_cast<i18n_file *>(who->contr->language);
48  auto found = file->messages.find(scode);
49  free_string(scode);
50 
51  return found == file->messages.end() ? code : found->second;
52 }
53 
60  for (auto language : i18n_files) {
61  if (strcmp(code, language->code) == 0)
62  return language;
63  }
64 
65  return nullptr;
66 }
67 
75  if (found)
76  return found;
77  return i18n_default;
78 }
79 
86  if (!language)
87  return i18n_default->code;
88  return static_cast<i18n_file *>(language)->code;
89 }
90 
95 void i18n_list_languages(object *who) {
96  for (auto language : i18n_files) {
98  "[fixed]%s: %s",
99  language->code,
100  language->name
101  );
102  }
103 }
104 
113 static void convert_newline(char *line) {
114  char *next;
115  char buf[MAX_BUF];
116 
117  while ((next = strstr(line, "\\n")) != NULL) {
118  *next = '\n';
119  *(next+1) = '\0';
120  snprintf(buf, MAX_BUF, "%s%s", line, next+2);
121  strcpy(line, buf);
122  }
123 }
124 
130 void i18n_init(void) {
131  char dirname[MAX_BUF], filename[MAX_BUF*2], *line;
132  BufferReader *br;
133  char *token;
134  DIR *dir;
135  struct dirent *file;
136 
137  snprintf(dirname, sizeof(dirname), "%s/i18n/", settings.datadir);
138 
139  dir = opendir(dirname);
140  if (dir == NULL) {
141  LOG(llevError, "i18n: couldn't open %s\n", dirname);
143  }
144 
145  sstring code = add_string("LN");
146 
147  while ((file = readdir(dir)) != NULL) {
148  if (strncmp(file->d_name, "messages.", 9) != 0)
149  continue;
150 
151  snprintf(filename, sizeof(filename), "%s%s", dirname, file->d_name);
152  br = bufferreader_init_from_file(NULL, filename, "i18n: couldn't open %s: %s\n", llevError);
153  if (!br) {
155  }
156  i18n_file *language = new i18n_file();
157 
158  if (!language) {
159  LOG(llevError, "i18n: couldn't allocate memory!\n");
161  }
162  language->code = add_string(file->d_name + 9);
163  i18n_files.push_back(language);
164 
165  while ((line = bufferreader_next_line(br)) != NULL) {
166  if (line[0] != '#' && line[0] != '\0') {
167 
168  token = strtok(line, "|");
170  sstring scode = add_string(token), smessage;
171  token = strtok(NULL, "|");
172  if (token != NULL) {
174  smessage = add_string(token);
175  } else {
176  smessage = add_refcount(scode);
177  }
178  language->messages[scode] = smessage;
179  }
180  }
182 
183  auto found = language->messages.find(code);
184  if (found == language->messages.end()) {
185  LOG(llevError, "i18n: no language set in %s\n", filename);
187  }
188 
189  language->name = found->second;
190  LOG(llevDebug, "i18n: %zu strings for %s\n",
191  language->messages.size(), language->name);
192 
193  if (strcmp(language->code, "en") == 0)
194  i18n_default = language;
195  }
196  closedir(dir);
197 
198  free_string(code);
199 
200  if (i18n_default == nullptr) {
201  LOG(llevError, "i18n: couldn't find default language (en)\n");
203  }
204 }
205 
209 void i18n_free(void) {
210  for (auto language : i18n_files) {
211  free_string(language->code); /* name is a copy of a message */
212  for (auto message : language->messages) {
213  free_string(message.first);
214  free_string(message.second);
215  }
216  delete language;
217  }
218  i18n_files.clear();
219 }
give.next
def next
Definition: give.py:44
global.h
i18n_free
void i18n_free(void)
Definition: languages.cpp:209
settings
struct Settings settings
Definition: init.cpp:139
i18n_files
static std::vector< i18n_file * > i18n_files
Definition: languages.cpp:32
llevError
@ llevError
Definition: logger.h:11
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:58
language_t
void * language_t
Definition: global.h:67
token
Definition: token.py:1
Settings::datadir
const char * datadir
Definition: global.h:248
i18n_file::messages
std::map< sstring, sstring > messages
Definition: languages.cpp:28
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,...) PRINTF_ARGS(6
mad_mage_user.file
file
Definition: mad_mage_user.py:15
bufferreader_destroy
void bufferreader_destroy(BufferReader *br)
Definition: bufferreader.cpp:40
i18n_file::name
sstring name
Definition: languages.cpp:27
SEE_LAST_ERROR
@ SEE_LAST_ERROR
Definition: define.h:52
npc_dialog.filename
filename
Definition: npc_dialog.py:99
buf
StringBuffer * buf
Definition: readable.cpp:1565
MSG_TYPE_COMMAND
#define MSG_TYPE_COMMAND
Definition: newclient.h:393
i18n_init
void i18n_init(void)
Definition: languages.cpp:130
autojail.who
who
Definition: autojail.py:3
bufferreader_init_from_file
BufferReader * bufferreader_init_from_file(BufferReader *br, const char *filepath, const char *failureMessage, LogLevel failureLevel)
Definition: bufferreader.cpp:65
opendir
DIR * opendir(const char *)
is_valid_types_gen.line
line
Definition: is_valid_types_gen.py:34
add_refcount
sstring add_refcount(sstring str)
Definition: shstr.cpp:210
i18n_get_language_code
sstring i18n_get_language_code(language_t language)
Definition: languages.cpp:85
add_string
sstring add_string(const char *str)
Definition: shstr.cpp:124
readdir
struct dirent * readdir(DIR *)
i18n_file
Definition: languages.cpp:25
MSG_SUBTYPE_NONE
#define MSG_SUBTYPE_NONE
Definition: newclient.h:409
fatal
void fatal(enum fatal_error err)
Definition: utils.cpp:590
MAX_BUF
#define MAX_BUF
Definition: define.h:35
free_string
void free_string(sstring str)
Definition: shstr.cpp:280
is_valid_types_gen.found
found
Definition: is_valid_types_gen.py:39
diamondslots.message
string message
Definition: diamondslots.py:57
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:251
i18n_get_language_by_code
language_t i18n_get_language_by_code(const char *code)
Definition: languages.cpp:73
sstring
const typedef char * sstring
Definition: sstring.h:2
i18n_list_languages
void i18n_list_languages(object *who)
Definition: languages.cpp:95
i18n_find_language_by_code
language_t i18n_find_language_by_code(const char *code)
Definition: languages.cpp:59
i18n_file::code
sstring code
Definition: languages.cpp:26
closedir
int closedir(DIR *)
OUT_OF_MEMORY
@ OUT_OF_MEMORY
Definition: define.h:48
BufferReader
Definition: bufferreader.cpp:21
i18n_default
static i18n_file * i18n_default
Definition: languages.cpp:34
llevDebug
@ llevDebug
Definition: logger.h:13
i18n
const char * i18n(const object *who, const char *code)
Definition: languages.cpp:42
convert_newline
static void convert_newline(char *line)
Definition: languages.cpp:113
bufferreader_next_line
char * bufferreader_next_line(BufferReader *br)
Definition: bufferreader.cpp:102