MyGUI  3.0.1
MyGUI_LanguageManager.cpp
Go to the documentation of this file.
1 
7 /*
8  This file is part of MyGUI.
9 
10  MyGUI is free software: you can redistribute it and/or modify
11  it under the terms of the GNU Lesser General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  (at your option) any later version.
14 
15  MyGUI is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public License
21  along with MyGUI. If not, see <http://www.gnu.org/licenses/>.
22 */
23 #include "MyGUI_Precompiled.h"
24 #include "MyGUI_ResourceManager.h"
25 #include "MyGUI_LanguageManager.h"
26 #include "MyGUI_XmlDocument.h"
27 #include "MyGUI_DataManager.h"
28 #include "MyGUI_FactoryManager.h"
29 
30 namespace MyGUI
31 {
32 
33  const std::string XML_TYPE("Language");
34 
35  MYGUI_INSTANCE_IMPLEMENT( LanguageManager )
36 
37  void LanguageManager::initialise()
38  {
39  MYGUI_ASSERT(!mIsInitialise, INSTANCE_TYPE_NAME << " initialised twice");
40  MYGUI_LOG(Info, "* Initialise: " << INSTANCE_TYPE_NAME);
41 
43 
44  MYGUI_LOG(Info, INSTANCE_TYPE_NAME << " successfully initialized");
45  mIsInitialise = true;
46  }
47 
49  {
50  if (!mIsInitialise) return;
51  MYGUI_LOG(Info, "* Shutdown: " << INSTANCE_TYPE_NAME);
52 
53  ResourceManager::getInstance().unregisterLoadXmlDelegate(XML_TYPE);
54 
55  MYGUI_LOG(Info, INSTANCE_TYPE_NAME << " successfully shutdown");
56  mIsInitialise = false;
57  }
58 
59  bool LanguageManager::load(const std::string& _file)
60  {
61  return ResourceManager::getInstance()._loadImplement(_file, true, XML_TYPE, INSTANCE_TYPE_NAME);
62  }
63 
64  void LanguageManager::_load(xml::ElementPtr _node, const std::string& _file, Version _version)
65  {
66  std::string default_lang;
67  bool event_change = false;
68 
69  // берем детей и крутимся, основной цикл
71  while (root.next(XML_TYPE))
72  {
73  // парсим атрибуты
74  root->findAttribute("default", default_lang);
75 
76  // берем детей и крутимся
78  while (info.next("Info"))
79  {
80  // парсим атрибуты
81  std::string name(info->findAttribute("name"));
82 
83  // доюавляем в карту пользователя
84  if (name.empty())
85  {
86  xml::ElementEnumerator source_info = info->getElementEnumerator();
87  while (source_info.next("Source"))
88  {
89  loadLanguage(source_info->getContent(), true);
90  }
91  }
92  // добавляем в карту языков
93  else
94  {
95  xml::ElementEnumerator source_info = info->getElementEnumerator();
96  while (source_info.next("Source"))
97  {
98  std::string file_source = source_info->getContent();
99  // добавляем в карту
100  mMapFile[name].push_back(file_source);
101 
102  // если добавляемый файл для текущего языка, то подгружаем и оповещаем
103  if (name == mCurrentLanguageName)
104  {
105  loadLanguage(file_source, false);
106  event_change = true;
107  }
108  }
109  }
110 
111  }
112  }
113 
114  if (!default_lang.empty())
115  setCurrentLanguage(default_lang);
116  else if (event_change)
117  eventChangeLanguage(mCurrentLanguageName);
118  }
119 
120  void LanguageManager::setCurrentLanguage(const std::string& _name)
121  {
122  mMapLanguage.clear();
123 
124  mCurrentLanguageName = _name;
125 
126  MapListString::iterator item = mMapFile.find(_name);
127  if (item == mMapFile.end())
128  {
129  MYGUI_LOG(Error, "Language '" << _name << "' is not found");
130  return;
131  }
132 
133  for (VectorString::const_iterator iter=item->second.begin(); iter!=item->second.end(); ++iter)
134  {
135  loadLanguage(*iter, false);
136  }
137 
138  eventChangeLanguage(mCurrentLanguageName);
139  }
140 
141  bool LanguageManager::loadLanguage(const std::string& _file, bool _user)
142  {
143  IDataStream* data = DataManager::getInstance().getData(_file);
144  if (data == nullptr)
145  {
146  MYGUI_LOG(Error, "file '" << _file << "' not found");
147  return false;
148  }
149 
150  if (_file.find(".xml") != std::string::npos)
151  _loadLanguageXML(data, _user);
152  else
153  _loadLanguage(data, _user);
154 
155  delete data;
156  return true;
157  }
158 
159  void LanguageManager::_loadLanguageXML(IDataStream* _stream, bool _user)
160  {
161  xml::Document doc;
162  // формат xml
163  if (doc.open(_stream))
164  {
165  xml::ElementPtr root = doc.getRoot();
166  if (root)
167  {
168  xml::ElementEnumerator tag = root->getElementEnumerator();
169  while (tag.next("Tag"))
170  {
171  if (_user)
172  mUserMapLanguage[tag->findAttribute("name")] = tag->getContent();
173  else
174  mMapLanguage[tag->findAttribute("name")] = tag->getContent();
175  }
176  }
177  }
178  }
179 
180  void LanguageManager::_loadLanguage(IDataStream* _stream, bool _user)
181  {
182  // формат txt
183  std::string read;
184  while (!_stream->eof())
185  {
186  _stream->readline(read, '\n');
187  if (read.empty()) continue;
188 
189  // заголовок утф
190  if ((uint8)read[0] == 0xEF && read.size() > 2)
191  {
192  read.erase(0, 3);
193  }
194 
195  if (read[read.size()-1] == '\r') read.erase(read.size()-1, 1);
196  if (read.empty()) continue;
197 
198  size_t pos = read.find_first_of(" \t");
199  if (_user)
200  {
201  if (pos == std::string::npos) mUserMapLanguage[read] = "";
202  else mUserMapLanguage[read.substr(0, pos)] = read.substr(pos+1, std::string::npos);
203  }
204  else
205  {
206  if (pos == std::string::npos) mMapLanguage[read] = "";
207  else mMapLanguage[read.substr(0, pos)] = read.substr(pos+1, std::string::npos);
208  }
209  }
210  }
211 
213  {
214  // вот хз, что быстрее, итераторы или математика указателей,
215  // для непонятно какого размера одного символа UTF8
216  UString line(_line);
217 
218  if (mMapLanguage.empty() && mUserMapLanguage.empty())
219  return _line;
220 
221  UString::iterator end = line.end();
222  for (UString::iterator iter=line.begin(); iter!=end; )
223  {
224  if (*iter == '#')
225  {
226  ++iter;
227  if (iter == end)
228  {
229  return line;
230  }
231  else
232  {
233  if (*iter != '{')
234  {
235  ++iter;
236  continue;
237  }
238  UString::iterator iter2 = iter;
239  ++iter2;
240  while (true)
241  {
242  if (iter2 == end) return line;
243  if (*iter2 == '}')
244  {
245  size_t start = iter - line.begin();
246  size_t len = (iter2 - line.begin()) - start - 1;
247  const UString& tag = line.substr(start + 1, len);
248 
249  bool find = true;
250  MapLanguageString::iterator replace = mMapLanguage.find(tag);
251  if (replace == mMapLanguage.end())
252  {
253  replace = mUserMapLanguage.find(tag);
254  find = replace != mUserMapLanguage.end();
255  }
256 
257  if (!find)
258  {
259  iter = line.insert(iter, '#') + size_t(len + 2);
260  end = line.end();
261  break;
262  }
263 
264  iter = line.erase(iter - size_t(1), iter2 + size_t(1));
265  size_t pos = iter - line.begin();
266  line.insert(pos, replace->second);
267  iter = line.begin() + pos + replace->second.length();
268  end = line.end();
269  if (iter == end) return line;
270  break;
271 
272  }
273  ++iter2;
274  }
275  }
276  }
277  else
278  {
279  ++iter;
280  }
281  }
282 
283  return line;
284  }
285 
287  {
288  MapLanguageString::iterator iter = mMapLanguage.find(_tag);
289  if (iter == mMapLanguage.end())
290  {
291  iter = mUserMapLanguage.find(_tag);
292  if (iter != mUserMapLanguage.end()) return iter->second;
293  return _tag;
294  }
295 
296  return iter->second;
297  }
298 
300  {
301  return mCurrentLanguageName;
302  }
303 
304  void LanguageManager::addUserTag(const UString& _tag, const UString& _replace)
305  {
306  mUserMapLanguage[_tag] = _replace;
307  }
308 
310  {
311  mUserMapLanguage.clear();
312  }
313 
314  bool LanguageManager::loadUserTags(const std::string& _file)
315  {
316  return loadLanguage(_file, true);
317  }
318 
319 } // namespace MyGUI