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