MyGUI
3.2.1
|
00001 /* 00002 * This source file is part of MyGUI. For the latest info, see http://mygui.info/ 00003 * Distributed under the MIT License 00004 * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT) 00005 */ 00006 00007 #include "MyGUI_Precompiled.h" 00008 #include "MyGUI_LanguageManager.h" 00009 #include "MyGUI_ResourceManager.h" 00010 #include "MyGUI_XmlDocument.h" 00011 #include "MyGUI_DataManager.h" 00012 #include "MyGUI_FactoryManager.h" 00013 #include "MyGUI_DataStreamHolder.h" 00014 00015 namespace MyGUI 00016 { 00017 00018 template <> LanguageManager* Singleton<LanguageManager>::msInstance = nullptr; 00019 template <> const char* Singleton<LanguageManager>::mClassTypeName = "LanguageManager"; 00020 00021 LanguageManager::LanguageManager() : 00022 mIsInitialise(false), 00023 mXmlLanguageTagName("Language") 00024 { 00025 } 00026 00027 void LanguageManager::initialise() 00028 { 00029 MYGUI_ASSERT(!mIsInitialise, getClassTypeName() << " initialised twice"); 00030 MYGUI_LOG(Info, "* Initialise: " << getClassTypeName()); 00031 00032 ResourceManager::getInstance().registerLoadXmlDelegate(mXmlLanguageTagName) = newDelegate(this, &LanguageManager::_load); 00033 00034 MYGUI_LOG(Info, getClassTypeName() << " successfully initialized"); 00035 mIsInitialise = true; 00036 } 00037 00038 void LanguageManager::shutdown() 00039 { 00040 MYGUI_ASSERT(mIsInitialise, getClassTypeName() << " is not initialised"); 00041 MYGUI_LOG(Info, "* Shutdown: " << getClassTypeName()); 00042 00043 ResourceManager::getInstance().unregisterLoadXmlDelegate(mXmlLanguageTagName); 00044 00045 MYGUI_LOG(Info, getClassTypeName() << " successfully shutdown"); 00046 mIsInitialise = false; 00047 } 00048 00049 void LanguageManager::_load(xml::ElementPtr _node, const std::string& _file, Version _version) 00050 { 00051 std::string default_lang; 00052 bool event_change = false; 00053 00054 // берем детей и крутимся, основной цикл 00055 xml::ElementEnumerator root = _node->getElementEnumerator(); 00056 while (root.next(mXmlLanguageTagName)) 00057 { 00058 // парсим атрибуты 00059 root->findAttribute("default", default_lang); 00060 00061 // берем детей и крутимся 00062 xml::ElementEnumerator info = root->getElementEnumerator(); 00063 while (info.next("Info")) 00064 { 00065 // парсим атрибуты 00066 std::string name(info->findAttribute("name")); 00067 00068 // доюавляем в карту пользователя 00069 if (name.empty()) 00070 { 00071 xml::ElementEnumerator source_info = info->getElementEnumerator(); 00072 while (source_info.next("Source")) 00073 { 00074 loadLanguage(source_info->getContent(), true); 00075 } 00076 } 00077 // добавляем в карту языков 00078 else 00079 { 00080 xml::ElementEnumerator source_info = info->getElementEnumerator(); 00081 while (source_info.next("Source")) 00082 { 00083 std::string file_source = source_info->getContent(); 00084 // добавляем в карту 00085 mMapFile[name].push_back(file_source); 00086 00087 // если добавляемый файл для текущего языка, то подгружаем и оповещаем 00088 if (name == mCurrentLanguageName) 00089 { 00090 loadLanguage(file_source, false); 00091 event_change = true; 00092 } 00093 } 00094 } 00095 00096 } 00097 } 00098 00099 if (!default_lang.empty()) 00100 setCurrentLanguage(default_lang); 00101 else if (event_change) 00102 eventChangeLanguage(mCurrentLanguageName); 00103 } 00104 00105 void LanguageManager::setCurrentLanguage(const std::string& _name) 00106 { 00107 MapListString::iterator item = mMapFile.find(_name); 00108 if (item == mMapFile.end()) 00109 { 00110 MYGUI_LOG(Error, "Language '" << _name << "' is not found"); 00111 return; 00112 } 00113 00114 mMapLanguage.clear(); 00115 mCurrentLanguageName = _name; 00116 00117 for (VectorString::const_iterator iter = item->second.begin(); iter != item->second.end(); ++iter) 00118 { 00119 loadLanguage(*iter, false); 00120 } 00121 00122 eventChangeLanguage(mCurrentLanguageName); 00123 } 00124 00125 bool LanguageManager::loadLanguage(const std::string& _file, bool _user) 00126 { 00127 DataStreamHolder data = DataManager::getInstance().getData(_file); 00128 if (data.getData() == nullptr) 00129 { 00130 MYGUI_LOG(Error, "file '" << _file << "' not found"); 00131 return false; 00132 } 00133 00134 if (_file.find(".xml") != std::string::npos) 00135 _loadLanguageXML(data.getData(), _user); 00136 else 00137 _loadLanguage(data.getData(), _user); 00138 00139 return true; 00140 } 00141 00142 void LanguageManager::_loadLanguageXML(IDataStream* _stream, bool _user) 00143 { 00144 xml::Document doc; 00145 // формат xml 00146 if (doc.open(_stream)) 00147 { 00148 xml::ElementPtr root = doc.getRoot(); 00149 if (root) 00150 { 00151 xml::ElementEnumerator tag = root->getElementEnumerator(); 00152 while (tag.next("Tag")) 00153 { 00154 if (_user) 00155 mUserMapLanguage[tag->findAttribute("name")] = tag->getContent(); 00156 else 00157 mMapLanguage[tag->findAttribute("name")] = tag->getContent(); 00158 } 00159 } 00160 } 00161 } 00162 00163 void LanguageManager::_loadLanguage(IDataStream* _stream, bool _user) 00164 { 00165 // формат txt 00166 std::string read; 00167 while (!_stream->eof()) 00168 { 00169 _stream->readline(read, '\n'); 00170 if (read.empty()) continue; 00171 00172 // заголовок утф 00173 if ((uint8)read[0] == 0xEF && read.size() > 2) 00174 { 00175 read.erase(0, 3); 00176 } 00177 00178 if (read[read.size() - 1] == '\r') read.erase(read.size() - 1, 1); 00179 if (read.empty()) continue; 00180 00181 size_t pos = read.find_first_of(" \t"); 00182 if (_user) 00183 { 00184 if (pos == std::string::npos) mUserMapLanguage[read] = ""; 00185 else mUserMapLanguage[read.substr(0, pos)] = read.substr(pos + 1, std::string::npos); 00186 } 00187 else 00188 { 00189 if (pos == std::string::npos) mMapLanguage[read] = ""; 00190 else mMapLanguage[read.substr(0, pos)] = read.substr(pos + 1, std::string::npos); 00191 } 00192 } 00193 } 00194 00195 UString LanguageManager::replaceTags(const UString& _line) 00196 { 00197 UString result(_line); 00198 00199 bool replace = false; 00200 do 00201 { 00202 result = replaceTagsPass(result, replace); 00203 } 00204 while (replace); 00205 00206 return result; 00207 } 00208 00209 UString LanguageManager::getTag(const UString& _tag) 00210 { 00211 MapLanguageString::iterator iter = mMapLanguage.find(_tag); 00212 if (iter != mMapLanguage.end()) 00213 { 00214 return iter->second; 00215 } 00216 00217 MapLanguageString::iterator iterUser = mUserMapLanguage.find(_tag); 00218 if (iterUser != mUserMapLanguage.end()) 00219 { 00220 return iterUser->second; 00221 } 00222 00223 return _tag; 00224 } 00225 00226 const std::string& LanguageManager::getCurrentLanguage() const 00227 { 00228 return mCurrentLanguageName; 00229 } 00230 00231 void LanguageManager::addUserTag(const UString& _tag, const UString& _replace) 00232 { 00233 mUserMapLanguage[_tag] = _replace; 00234 } 00235 00236 void LanguageManager::clearUserTags() 00237 { 00238 mUserMapLanguage.clear(); 00239 } 00240 00241 bool LanguageManager::loadUserTags(const std::string& _file) 00242 { 00243 return loadLanguage(_file, true); 00244 } 00245 00246 UString LanguageManager::replaceTagsPass(const UString& _line, bool& _replaceResult) 00247 { 00248 _replaceResult = false; 00249 00250 // вот хз, что быстрее, итераторы или математика указателей, 00251 // для непонятно какого размера одного символа UTF8 00252 UString line(_line); 00253 00254 UString::iterator end = line.end(); 00255 for (UString::iterator iter = line.begin(); iter != end; ) 00256 { 00257 if (*iter == '#') 00258 { 00259 ++iter; 00260 if (iter == end) 00261 { 00262 return line; 00263 } 00264 else 00265 { 00266 if (*iter != '{') 00267 { 00268 ++iter; 00269 continue; 00270 } 00271 UString::iterator iter2 = iter; 00272 ++iter2; 00273 00274 while (true) 00275 { 00276 if (iter2 == end) 00277 return line; 00278 00279 if (*iter2 == '}') 00280 { 00281 size_t start = iter - line.begin(); 00282 size_t len = (iter2 - line.begin()) - start - 1; 00283 const UString& tag = line.substr(start + 1, len); 00284 UString replacement; 00285 00286 bool find = true; 00287 // try to find in loaded from resources language strings 00288 MapLanguageString::iterator replace = mMapLanguage.find(tag); 00289 if (replace != mMapLanguage.end()) 00290 { 00291 replacement = replace->second; 00292 } 00293 else 00294 { 00295 // try to find in user language strings 00296 replace = mUserMapLanguage.find(tag); 00297 if (replace != mUserMapLanguage.end()) 00298 { 00299 replacement = replace->second; 00300 } 00301 else 00302 { 00303 find = false; 00304 } 00305 } 00306 00307 // try to ask user if event assigned or use #{_tag} instead 00308 if (!find) 00309 { 00310 if (!eventRequestTag.empty()) 00311 { 00312 eventRequestTag(tag, replacement); 00313 } 00314 else 00315 { 00316 iter = line.insert(iter, '#') + size_t(len + 2); 00317 end = line.end(); 00318 break; 00319 } 00320 } 00321 00322 _replaceResult = true; 00323 00324 iter = line.erase(iter - size_t(1), iter2 + size_t(1)); 00325 size_t pos = iter - line.begin(); 00326 line.insert(pos, replacement); 00327 iter = line.begin() + pos + replacement.length(); 00328 end = line.end(); 00329 if (iter == end) 00330 return line; 00331 break; 00332 } 00333 ++iter2; 00334 } 00335 } 00336 } 00337 else 00338 { 00339 ++iter; 00340 } 00341 } 00342 00343 return line; 00344 } 00345 00346 } // namespace MyGUI