1 /*=============================================================================
2 Blobby Volley 2
3 Copyright (C) 2006 Jonathan Sieber (jonathan_sieber@yahoo.de)
4 Copyright (C) 2006 Daniel Knobe (daniel-knobe@web.de)
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 =============================================================================*/
20
21 /* header include */
22 #include "TextManager.h"
23
24 /* includes */
25 #include <iostream>
26 #include <algorithm>
27 #include <set>
28
29 #include "tinyxml/tinyxml.h"
30
31 #include "Global.h"
32 #include "FileRead.h"
33
34 /* implementation */
35 TextManager* TextManager::mSingleton = 0;
36
37
createTextManager(std::string langname)38 TextManager* TextManager::createTextManager(std::string langname){
39 delete mSingleton;
40
41 mSingleton = new TextManager(langname);
42
43 std::string langfile = "lang_"+langname+".xml";
44
45 bool loaded = false;
46 try{
47 loaded = mSingleton->loadFromXML(langfile);
48 }catch(FileLoadException& fle){
49 std::cerr << fle.what() << std::endl;
50 };
51
52 if(!loaded){
53 std::cerr << "error loading language " << langfile << "!" << std::endl;
54 std::cerr << "\tfalling back to english" << std::endl;
55 }
56
57 return mSingleton;
58 }
59
getSingleton()60 const TextManager* TextManager::getSingleton(){
61 return mSingleton;
62 }
63
TextManager(std::string l)64 TextManager::TextManager(std::string l):lang(l){
65 mStrings.resize(COUNT);
66 setDefault();
67 }
68
switchLanguage(std::string langname)69 void TextManager::switchLanguage(std::string langname){
70 // if old and new language are the same, nothing must be done
71 if(langname == mSingleton->lang)
72 return;
73
74 // otherwise, the old TextManager is destroyed and a new one is created
75 createTextManager(langname);
76 }
77
getString(STRING str) const78 const std::string& TextManager::getString(STRING str) const{
79 return mStrings[str];
80 }
getLang() const81 std::string TextManager::getLang() const{
82 return lang;
83 }
84
85 /// \todo why no const std::string& ?
loadFromXML(std::string filename)86 bool TextManager::loadFromXML(std::string filename){
87 // read and parse file
88 boost::shared_ptr<TiXmlDocument> language_data = FileRead::readXMLDocument(filename);
89
90 if (language_data->Error())
91 {
92 std::cerr << "Warning: Parse error in " << filename;
93 std::cerr << "!" << std::endl;
94 }
95
96 TiXmlElement* language = language_data->FirstChildElement("language");
97 if (!language)
98 return false;
99
100 int num_strings = mStrings.size();
101 int found_count = 0;
102
103 #ifdef DEBUG
104 std::set<std::string> stringsToTranslate;
105 for(std::string s: mStrings)
106 {
107 stringsToTranslate.insert( s );
108 }
109 #endif // DEBUG
110
111 // this loop assumes that the strings in the xml file are in the correct order
112 // in each step, it reads the next string element and writes it to the next position in mStrings
113 for ( TiXmlElement* stringel = language->FirstChildElement("string");
114 stringel;
115 stringel = stringel->NextSiblingElement("string"))
116
117 {
118
119 /// \todo we don't check for duplicate entries!
120 const char* e = stringel->Attribute("english");
121 const char* t = stringel->Attribute("translation");
122 if (t && e)
123 {
124 #ifdef DEBUG
125 // remove every found element
126 stringsToTranslate.erase( std::string(e) );
127 #endif // DEBUG
128 // search the english string and replace it with the translation
129 std::vector<std::string>::iterator found = std::find(mStrings.begin(), mStrings.end(), e);
130 if(found != mStrings.end())
131 {
132 found_count++;
133 *found = t;
134 }
135 else
136 std::cerr << "error in language file: entry " << e << " -> " << t << " invalid\n";
137
138 }
139 else if(t)
140 {
141 std::cerr << "error in language file: english not found for " << t << std::endl;
142 }
143 else if(e)
144 {
145 std::cerr << "error in language file: translation not found for " << e << std::endl;
146 }
147
148 }
149
150 // do we check if we got all?
151 if(num_strings != found_count)
152 {
153 std::cerr << "missing translations: got " << found_count <<
154 " out of " << num_strings << " translation entries" << std::endl;
155
156 #ifdef DEBUG
157 for(auto e : stringsToTranslate)
158 {
159 std::cerr << " missing " << e << "\n";
160 }
161 #endif // DEBUG
162 }
163
164 return true;
165 }
166
setDefault()167 void TextManager::setDefault()
168 {
169 // Hardcoded default language
170 mStrings[LBL_OK] = "ok";
171 mStrings[LBL_CANCEL] = "cancel";
172 mStrings[LBL_YES] = "yes";
173 mStrings[LBL_NO] = "no";
174 mStrings[LBL_CONF_QUIT] = "really quit?";
175 mStrings[LBL_CONTINUE] = "continue";
176
177 mStrings[MNU_LABEL_ONLINE] = "online game";
178 mStrings[MNU_LABEL_LAN] = "lan game";
179 mStrings[MNU_LABEL_START] = "start";
180 mStrings[MNU_LABEL_OPTIONS] = "options";
181 mStrings[MNU_LABEL_REPLAY] = "watch replay";
182 mStrings[MNU_LABEL_CREDITS] = "credits";
183 mStrings[MNU_LABEL_EXIT] = "exit";
184
185 mStrings[CRD_PROGRAMMERS] = "programmers:";
186 mStrings[CRD_GRAPHICS] = "graphics:";
187 mStrings[CRD_THX] = "special thanks at:";
188
189 mStrings[RP_SHOW_AGAIN] = "show again";
190 mStrings[RP_PLAY] = "play";
191 mStrings[RP_DELETE] = "delete";
192 mStrings[RP_INFO] = "info";
193 mStrings[RP_DURATION] = "duration:";
194 mStrings[RP_RESULT] = "result:";
195 mStrings[RP_CHECKSUM] = "checksum error";
196 mStrings[RP_FILE_CORRUPT] = "file is corrupt";
197 mStrings[RP_VERSION] = "version error";
198 mStrings[RP_FILE_OUTDATED] = "file is outdated";
199 mStrings[RP_SAVE_NAME] = "name of the replay:";
200 mStrings[RP_WAIT_REPLAY] = "receiving replay...";
201 mStrings[RP_SAVE] = "save replay";
202
203 mStrings[GAME_WIN] = "has won the game!";
204 mStrings[GAME_TRY_AGAIN] = "try again";
205 mStrings[GAME_WAITING] = "waiting for opponent...";
206 mStrings[GAME_OPP_LEFT] = "opponent left the game";
207 mStrings[GAME_PAUSED] = "game paused";
208 mStrings[GAME_QUIT] = "quit";
209
210 mStrings[NET_SERVER_SCAN] = "scan for servers";
211 mStrings[NET_DIRECT_CONNECT] = "direct connect";
212 mStrings[NET_SERVER_INFO] = "server info";
213 mStrings[NET_ACTIVE_GAMES] = "games: ";
214 mStrings[NET_WAITING_PLAYER] = "waiting player: ";
215 mStrings[NET_HOST_GAME] = "host game";
216 mStrings[NET_CONNECTING] = "connecting to server ...";
217 mStrings[NET_DISCONNECT] = "disconnected from server";
218 mStrings[NET_CON_FAILED] = "connection failed";
219 mStrings[NET_SERVER_FULL] = "server full";
220 mStrings[NET_STAY_ON_SERVER] = "stay on server";
221 mStrings[NET_RANDOM_OPPONENT] = "random";
222 mStrings[NET_SPEED] = "speed: ";
223 mStrings[NET_RULES_TITLE] = "rules: ";
224 mStrings[NET_RULES_BY] = " by ";
225 mStrings[NET_CHALLENGE] = "challenger: ";
226
227 mStrings[OP_TOUCH_TYPE] = "touch input type:";
228 mStrings[OP_TOUCH_ARROWS] = "arrow keys";
229 mStrings[OP_TOUCH_DIRECT] = "blobby follows finger";
230 mStrings[OP_INPUT_OP] = "input options";
231 mStrings[OP_GFX_OP] = "graphic options";
232 mStrings[OP_MISC] = "misc options";
233 mStrings[OP_VIDEO] = "video settings";
234 mStrings[OP_FULLSCREEN] = "fullscreen mode";
235 mStrings[OP_WINDOW] = "window mode";
236 mStrings[OP_RENDER_DEVICE] = "render device";
237 mStrings[OP_SHOW_SHADOW] = "show shadow";
238 mStrings[OP_BLOB_COLORS] = "blob colors";
239 mStrings[OP_LEFT_PLAYER] = "left player";
240 mStrings[OP_RIGHT_PLAYER] = "right player";
241 mStrings[OP_RED] = "red";
242 mStrings[OP_GREEN] = "green";
243 mStrings[OP_BLUE] = "blue";
244 mStrings[OP_MORPHING] = "morphing blob?";
245 mStrings[OP_KEYBOARD] = "keyboard";
246 mStrings[OP_MOUSE] = "mouse";
247 mStrings[OP_JOYSTICK] = "joystick";
248 mStrings[OP_JUMP_BUTTON] = "jump button";
249 mStrings[OP_SET_ALL] = "set all";
250 mStrings[OP_LEFT_KEY] = "left key";
251 mStrings[OP_RIGHT_KEY] = "right key";
252 mStrings[OP_JUMP_KEY] = "jump key";
253 mStrings[OP_LEFT_BUTTON] = "left button";
254 mStrings[OP_RIGHT_BUTTON] = "right button";
255 mStrings[OP_PRESS_MOUSE_BUTTON] = "press mouse button for";
256 mStrings[OP_PRESS_KEY_FOR] = "press key for";
257 mStrings[OP_MOVING_LEFT] = "moving left";
258 mStrings[OP_MOVING_RIGHT] = "moving right";
259 mStrings[OP_JUMPING] = "jumping";
260 mStrings[OP_PRESS_BUTTON_FOR] = "press button for";
261 mStrings[OP_BACKGROUND] = "background:";
262 mStrings[OP_VOLUME] = "volume:";
263 mStrings[OP_MUTE] = "mute";
264 mStrings[OP_FPS] = "show fps";
265 mStrings[OP_BLOOD] = "show blood";
266 mStrings[OP_NETWORK_SIDE] = "network side:";
267 mStrings[OP_LEFT] = "left";
268 mStrings[OP_RIGHT] = "right";
269 mStrings[OP_SPEED] = "gamespeed:";
270 mStrings[OP_VSLOW] = "very slow";
271 mStrings[OP_SLOW] = "slow";
272 mStrings[OP_DEFAULT] = "default";
273 mStrings[OP_FAST] = "fast";
274 mStrings[OP_VFAST] = "very fast";
275 mStrings[OP_LANGUAGE] = "language";
276 mStrings[OP_DIFFICULTY] = "bot strength";
277 mStrings[OP_WEAK] = "weak";
278 mStrings[OP_MEDIUM] = "medium";
279 mStrings[OP_STRONG] = "strong";
280 mStrings[OP_RULES] = "rules:";
281
282 mStrings[UPDATE_NOTIFICATION] = "please visit http://blobby.sourceforge.net/ for a new version of blobby volley";
283 }
284
285 std::map<std::string, std::string> TextManager::language_names;
286
287 struct lang_init{
lang_initlang_init288 lang_init(){
289 TextManager::language_names["de"] = "deutsch";
290 TextManager::language_names["en"] = "english";
291 TextManager::language_names["fr"] = "francais";
292 TextManager::language_names["it"] = "italiano";
293 }
294 };
295 static lang_init init;
296
297
298