MyGUI  3.4.1
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"
12 #include "MyGUI_FactoryManager.h"
13 #include "MyGUI_DataStreamHolder.h"
14 
15 namespace MyGUI
16 {
17 
19 
21  mIsInitialise(false),
22  mXmlLanguageTagName("Language"),
23  mSingletonHolder(this)
24  {
25  }
26 
28  {
29  MYGUI_ASSERT(!mIsInitialise, getClassTypeName() << " initialised twice");
30  MYGUI_LOG(Info, "* Initialise: " << getClassTypeName());
31 
32  ResourceManager::getInstance().registerLoadXmlDelegate(mXmlLanguageTagName) = 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, const std::string& _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  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 
99  if (!default_lang.empty())
100  setCurrentLanguage(default_lang);
101  else if (event_change)
102  eventChangeLanguage(mCurrentLanguageName);
103  }
104 
105  void LanguageManager::setCurrentLanguage(const std::string& _name)
106  {
107  MapListString::iterator item = mMapFile.find(_name);
108  if (item == mMapFile.end())
109  {
110  MYGUI_LOG(Error, "Language '" << _name << "' is not found");
111  return;
112  }
113 
114  mMapLanguage.clear();
115  mCurrentLanguageName = _name;
116 
117  for (VectorString::const_iterator iter = item->second.begin(); iter != item->second.end(); ++iter)
118  {
119  loadLanguage(*iter, false);
120  }
121 
122  eventChangeLanguage(mCurrentLanguageName);
123  }
124 
125  bool LanguageManager::loadLanguage(const std::string& _file, bool _user)
126  {
128  if (data.getData() == nullptr)
129  {
130  MYGUI_LOG(Error, "file '" << _file << "' not found");
131  return false;
132  }
133 
134  if (_file.find(".xml") != std::string::npos)
135  _loadLanguageXML(data.getData(), _user);
136  else
137  _loadLanguage(data.getData(), _user);
138 
139  return true;
140  }
141 
142  void LanguageManager::_loadLanguageXML(IDataStream* _stream, bool _user)
143  {
144  xml::Document doc;
145  // формат xml
146  if (doc.open(_stream))
147  {
148  xml::ElementPtr root = doc.getRoot();
149  if (root)
150  {
151  xml::ElementEnumerator tag = root->getElementEnumerator();
152  while (tag.next("Tag"))
153  {
154  if (_user)
155  mUserMapLanguage[tag->findAttribute("name")] = tag->getContent();
156  else
157  mMapLanguage[tag->findAttribute("name")] = tag->getContent();
158  }
159  }
160  }
161  }
162 
163  void LanguageManager::_loadLanguage(IDataStream* _stream, bool _user)
164  {
165  // формат txt
166  std::string read;
167  while (!_stream->eof())
168  {
169  _stream->readline(read, '\n');
170  if (read.empty()) continue;
171 
172  // заголовок утф
173  if ((uint8)read[0] == 0xEF && read.size() > 2)
174  {
175  read.erase(0, 3);
176  }
177 
178  if (read[read.size() - 1] == '\r') read.erase(read.size() - 1, 1);
179  if (read.empty()) continue;
180 
181  size_t pos = read.find_first_of(" \t");
182  if (_user)
183  {
184  if (pos == std::string::npos) mUserMapLanguage[read] = "";
185  else mUserMapLanguage[read.substr(0, pos)] = read.substr(pos + 1, std::string::npos);
186  }
187  else
188  {
189  if (pos == std::string::npos) mMapLanguage[read] = "";
190  else mMapLanguage[read.substr(0, pos)] = read.substr(pos + 1, std::string::npos);
191  }
192  }
193  }
194 
196  {
197  UString result(_line);
198 
199  bool replace = false;
200  do
201  {
202  result = replaceTagsPass(result, replace);
203  }
204  while (replace);
205 
206  return result;
207  }
208 
210  {
211  MapLanguageString::const_iterator iter = mMapLanguage.find(_tag);
212  if (iter != mMapLanguage.end())
213  {
214  return iter->second;
215  }
216 
217  MapLanguageString::const_iterator iterUser = mUserMapLanguage.find(_tag);
218  if (iterUser != mUserMapLanguage.end())
219  {
220  return iterUser->second;
221  }
222 
223  return _tag;
224  }
225 
226  const std::string& LanguageManager::getCurrentLanguage() const
227  {
228  return mCurrentLanguageName;
229  }
230 
233  {
234  VectorString result;
235  for (MapListString::const_iterator iter = mMapFile.begin(); iter != mMapFile.end(); ++iter)
236  {
237  result.push_back(iter->first);
238  }
239  return result;
240  }
241 
242  void LanguageManager::addUserTag(const UString& _tag, const UString& _replace)
243  {
244  mUserMapLanguage[_tag] = _replace;
245  }
246 
248  {
249  mUserMapLanguage.clear();
250  }
251 
252  bool LanguageManager::loadUserTags(const std::string& _file)
253  {
254  return loadLanguage(_file, true);
255  }
256 
257  UString LanguageManager::replaceTagsPass(const UString& _line, bool& _replaceResult)
258  {
259  _replaceResult = false;
260 
261  UString::utf32string line(_line.asUTF32());
262 
263  UString::utf32string::iterator end = line.end();
264  for (UString::utf32string::iterator iter = line.begin(); iter != end; )
265  {
266  if (*iter == '#')
267  {
268  ++iter;
269  if (iter == end)
270  {
271  return UString(line);
272  }
273  else
274  {
275  if (*iter != '{')
276  {
277  ++iter;
278  continue;
279  }
280  UString::utf32string::iterator iter2 = iter;
281  ++iter2;
282 
283  while (true)
284  {
285  if (iter2 == end)
286  return UString(line);
287 
288  if (*iter2 == '}')
289  {
290  size_t start = iter - line.begin();
291  size_t len = (iter2 - line.begin()) - start - 1;
292  const UString::utf32string & tag = line.substr(start + 1, len);
293  UString replacement;
294 
295  bool find = true;
296  // try to find in loaded from resources language strings
297  MapLanguageString::iterator replace = mMapLanguage.find(UString(tag));
298  if (replace != mMapLanguage.end())
299  {
300  replacement = replace->second;
301  }
302  else
303  {
304  // try to find in user language strings
305  replace = mUserMapLanguage.find(UString(tag));
306  if (replace != mUserMapLanguage.end())
307  {
308  replacement = replace->second;
309  }
310  else
311  {
312  find = false;
313  }
314  }
315 
316  // try to ask user if event assigned or use #{_tag} instead
317  if (!find)
318  {
319  if (!eventRequestTag.empty())
320  {
321  eventRequestTag(UString(tag), replacement);
322  }
323  else
324  {
325  iter = line.insert(iter, '#') + size_t(len + 2);
326  end = line.end();
327  break;
328  }
329  }
330 
331  _replaceResult = true;
332 
333  iter = line.erase(iter - size_t(1), iter2 + size_t(1));
334  size_t pos = iter - line.begin();
335  line.insert(pos, replacement.asUTF32());
336  iter = line.begin() + pos + replacement.length();
337  end = line.end();
338  if (iter == end)
339  return UString(line);
340  break;
341  }
342  ++iter2;
343  }
344  }
345  }
346  else
347  {
348  ++iter;
349  }
350  }
351 
352  return UString(line);
353  }
354 
355 } // namespace MyGUI
#define MYGUI_ASSERT(exp, dest)
#define MYGUI_LOG(level, text)
virtual IDataStream * getData(const std::string &_name) const =0
static DataManager & getInstance()
const std::string & getCurrentLanguage() const
delegates::CDelegate2< const UString &, UString & > eventRequestTag
static const char * getClassTypeName()
void addUserTag(const UString &_tag, const UString &_replace)
void setCurrentLanguage(const std::string &_name)
VectorString getLanguages() const
UString getTag(const UString &_tag) const
delegates::CMultiDelegate1< const std::string & > eventChangeLanguage
bool loadUserTags(const std::string &_file)
UString replaceTags(const UString &_line)
void unregisterLoadXmlDelegate(const std::string &_key)
static ResourceManager & getInstance()
LoadXmlDelegate & registerLoadXmlDelegate(const std::string &_key)
A UTF-16 string with implicit conversion to/from std::string and std::wstring.
const utf32string & asUTF32() const
returns the current string in UTF-32 form within a utf32string
std::basic_string< unicode_char > utf32string
string type used for returning UTF-32 formatted data
const std::string & getContent() const
ElementEnumerator getElementEnumerator()
bool findAttribute(const std::string &_name, std::string &_value)
Element * ElementPtr
std::vector< std::string > VectorString
Definition: MyGUI_Types.h:40
uint8_t uint8
Definition: MyGUI_Types.h:45
delegates::DelegateFunction< Args... > * newDelegate(void(*_func)(Args... args))
MYGUI_SINGLETON_DEFINITION(ClipboardManager)
float len(float x, float y)