MyGUI  3.2.1
MyGUI_LanguageManager.cpp
Go to the documentation of this file.
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