MyGUI 3.4.3
MyGUI_LanguageManager.cpp
Go to the documentation of this file.
1/*
2 * This source file is part of MyGUI. For the latest info, see http://mygui.info/
3 * Distributed under the MIT License
4 * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
5 */
6
7#include "MyGUI_Precompiled.h"
10#include "MyGUI_XmlDocument.h"
11#include "MyGUI_DataManager.h"
14
15namespace MyGUI
16{
17
19
21 mXmlLanguageTagName("Language"),
22 mSingletonHolder(this)
23 {
24 }
25
27 {
28 MYGUI_ASSERT(!mIsInitialise, getClassTypeName() << " initialised twice");
29 MYGUI_LOG(Info, "* Initialise: " << getClassTypeName());
30
32 newDelegate(this, &LanguageManager::_load);
33
34 MYGUI_LOG(Info, getClassTypeName() << " successfully initialized");
35 mIsInitialise = true;
36 }
37
39 {
40 MYGUI_ASSERT(mIsInitialise, getClassTypeName() << " is not initialised");
41 MYGUI_LOG(Info, "* Shutdown: " << getClassTypeName());
42
44
45 MYGUI_LOG(Info, getClassTypeName() << " successfully shutdown");
46 mIsInitialise = false;
47 }
48
49 void LanguageManager::_load(xml::ElementPtr _node, std::string_view /*_file*/, Version _version)
50 {
51 std::string default_lang;
52 bool event_change = false;
53
54 // берем детей и крутимся, основной цикл
56 while (root.next(mXmlLanguageTagName))
57 {
58 // парсим атрибуты
59 root->findAttribute("default", default_lang);
60
61 // берем детей и крутимся
63 while (info.next("Info"))
64 {
65 // парсим атрибуты
66 std::string name(info->findAttribute("name"));
67
68 // доюавляем в карту пользователя
69 if (name.empty())
70 {
71 xml::ElementEnumerator source_info = info->getElementEnumerator();
72 while (source_info.next("Source"))
73 {
74 loadLanguage(source_info->getContent(), true);
75 }
76 }
77 // добавляем в карту языков
78 else
79 {
80 xml::ElementEnumerator source_info = info->getElementEnumerator();
81 while (source_info.next("Source"))
82 {
83 const std::string& file_source = source_info->getContent();
84 // добавляем в карту
85 mMapFile[name].push_back(file_source);
86
87 // если добавляемый файл для текущего языка, то подгружаем и оповещаем
88 if (name == mCurrentLanguageName)
89 {
90 loadLanguage(file_source, false);
91 event_change = true;
92 }
93 }
94 }
95 }
96 }
97
98 if (!default_lang.empty())
99 setCurrentLanguage(default_lang);
100 else if (event_change)
101 eventChangeLanguage(mCurrentLanguageName);
102 }
103
104 void LanguageManager::setCurrentLanguage(std::string_view _name)
105 {
106 MapListString::iterator item = mMapFile.find(_name);
107 if (item == mMapFile.end())
108 {
109 MYGUI_LOG(Error, "Language '" << _name << "' is not found");
110 return;
111 }
112
113 mMapLanguage.clear();
114 mCurrentLanguageName = _name;
115
116 for (const auto& file : item->second)
117 {
118 loadLanguage(file, false);
119 }
120
121 eventChangeLanguage(mCurrentLanguageName);
122 }
123
124 bool LanguageManager::loadLanguage(const std::string& _file, bool _user)
125 {
127 if (data.getData() == nullptr)
128 {
129 MYGUI_LOG(Error, "file '" << _file << "' not found");
130 return false;
131 }
132
133 if (_file.find(".xml") != std::string::npos)
134 _loadLanguageXML(data.getData(), _user);
135 else
136 _loadLanguage(data.getData(), _user);
137
138 return true;
139 }
140
141 void LanguageManager::_loadLanguageXML(IDataStream* _stream, bool _user)
142 {
143 xml::Document doc;
144 // формат xml
145 if (doc.open(_stream))
146 {
147 xml::ElementPtr root = doc.getRoot();
148 if (root)
149 {
150 xml::ElementEnumerator tag = root->getElementEnumerator();
151 while (tag.next("Tag"))
152 {
153 auto& map = _user ? mUserMapLanguage : mMapLanguage;
154 mapSet(map, tag->findAttribute("name"), tag->getContent());
155 }
156 }
157 }
158 }
159
160 void LanguageManager::_loadLanguage(IDataStream* _stream, bool _user)
161 {
162 // формат txt
163 std::string read;
164 while (!_stream->eof())
165 {
166 _stream->readline(read, '\n');
167 if (read.empty())
168 continue;
169
170 // заголовок утф
171 if ((uint8)read[0] == 0xEF && read.size() > 2)
172 {
173 read.erase(0, 3);
174 }
175
176 if (read[read.size() - 1] == '\r')
177 read.erase(read.size() - 1, 1);
178 if (read.empty())
179 continue;
180
181 size_t pos = read.find_first_of(" \t");
182 if (_user)
183 {
184 if (pos == std::string::npos)
185 mUserMapLanguage[read].clear();
186 else
187 mUserMapLanguage[read.substr(0, pos)] = read.substr(pos + 1, std::string::npos);
188 }
189 else
190 {
191 if (pos == std::string::npos)
192 mMapLanguage[read].clear();
193 else
194 mMapLanguage[read.substr(0, pos)] = read.substr(pos + 1, std::string::npos);
195 }
196 }
197 }
198
200 {
201 UString result(_line);
202
203 bool replace = false;
204 do
205 {
206 result = replaceTagsPass(result, replace);
207 } while (replace);
208
209 return result;
210 }
211
213 {
214 MapLanguageString::const_iterator iter = mMapLanguage.find(_tag);
215 if (iter != mMapLanguage.end())
216 {
217 return iter->second;
218 }
219
220 MapLanguageString::const_iterator iterUser = mUserMapLanguage.find(_tag);
221 if (iterUser != mUserMapLanguage.end())
222 {
223 return iterUser->second;
224 }
225
226 return _tag;
227 }
228
229 const std::string& LanguageManager::getCurrentLanguage() const
230 {
231 return mCurrentLanguageName;
232 }
233
236 {
237 VectorString result;
238 for (const auto& iter : mMapFile)
239 {
240 result.push_back(iter.first);
241 }
242 return result;
243 }
244
245 void LanguageManager::addUserTag(const UString& _tag, const UString& _replace)
246 {
247 mUserMapLanguage[_tag] = _replace;
248 }
249
251 {
252 mUserMapLanguage.clear();
253 }
254
255 bool LanguageManager::loadUserTags(const std::string& _file)
256 {
257 return loadLanguage(_file, true);
258 }
259
260 UString LanguageManager::replaceTagsPass(const UString& _line, bool& _replaceResult)
261 {
262 _replaceResult = false;
263
264 UString::utf32string line(_line.asUTF32());
265
266 UString::utf32string::iterator end = line.end();
267 for (UString::utf32string::iterator iter = line.begin(); iter != end;)
268 {
269 if (*iter == '#')
270 {
271 ++iter;
272 if (iter == end)
273 {
274 return UString(line);
275 }
276
277 if (*iter != '{')
278 {
279 ++iter;
280 continue;
281 }
282 UString::utf32string::iterator iter2 = iter;
283 ++iter2;
284
285 while (true)
286 {
287 if (iter2 == end)
288 return UString(line);
289
290 if (*iter2 == '}')
291 {
292 size_t start = iter - line.begin();
293 size_t len = (iter2 - line.begin()) - start - 1;
294 const UString::utf32string& tag = line.substr(start + 1, len);
295 UString replacement;
296
297 bool find = true;
298 // try to find in loaded from resources language strings
299 MapLanguageString::iterator replace = mMapLanguage.find(UString(tag));
300 if (replace != mMapLanguage.end())
301 {
302 replacement = replace->second;
303 }
304 else
305 {
306 // try to find in user language strings
307 replace = mUserMapLanguage.find(UString(tag));
308 if (replace != mUserMapLanguage.end())
309 {
310 replacement = replace->second;
311 }
312 else
313 {
314 find = false;
315 }
316 }
317
318 // try to ask user if event assigned or use #{_tag} instead
319 if (!find)
320 {
321 if (!eventRequestTag.empty())
322 {
323 eventRequestTag(UString(tag), replacement);
324 }
325 else
326 {
327 iter = line.insert(iter, '#') + size_t(len + 2);
328 end = line.end();
329 break;
330 }
331 }
332
333 _replaceResult = true;
334
335 iter = line.erase(iter - size_t(1), iter2 + size_t(1));
336 size_t pos = iter - line.begin();
337 line.insert(pos, replacement.asUTF32());
338 iter = line.begin() + pos + replacement.length();
339 end = line.end();
340 if (iter == end)
341 return UString(line);
342 break;
343 }
344 ++iter2;
345 }
346 }
347 else
348 {
349 ++iter;
350 }
351 }
352
353 return UString(line);
354 }
355
356} // namespace MyGUI
#define MYGUI_ASSERT(exp, dest)
#define MYGUI_LOG(level, text)
#define MYGUI_SINGLETON_DEFINITION(ClassName)
virtual IDataStream * getData(const std::string &_name) const =0
static DataManager & getInstance()
LanguageManager(const LanguageManager &)=delete
delegates::MultiDelegate< const std::string & > eventChangeLanguage
void setCurrentLanguage(std::string_view _name)
const std::string & getCurrentLanguage() const
delegates::Delegate< const UString &, UString & > eventRequestTag
void addUserTag(const UString &_tag, const UString &_replace)
static std::string_view getClassTypeName()
VectorString getLanguages() const
UString getTag(const UString &_tag) const
bool loadUserTags(const std::string &_file)
UString replaceTags(const UString &_line)
void unregisterLoadXmlDelegate(std::string_view _key)
LoadXmlDelegate & registerLoadXmlDelegate(std::string_view _key)
static ResourceManager & getInstance()
A UTF-16 string with implicit conversion to/from std::string and std::wstring.
size_type find(const UString &str, size_type index=0) const
returns the index of the first occurrence of str within the current string, starting at index; return...
const utf32string & asUTF32() const
returns the current string in UTF-32 form within a utf32string
void clear()
deletes all of the elements in the string
std::basic_string< unicode_char > utf32string
string type used for returning UTF-32 formatted data
const std::string & getContent() const
bool findAttribute(std::string_view _name, std::string &_value)
ElementEnumerator getElementEnumerator()
Element * ElementPtr
uint8_t uint8
Definition MyGUI_Types.h:46
std::vector< std::string > VectorString
Definition MyGUI_Types.h:41
void mapSet(Map &map, std::string_view key, const Value &value)
delegates::DelegateFunction< Args... > * newDelegate(void(*_func)(Args... args))
float len(float x, float y)