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