MyGUI  3.0.3
MyGUI_LanguageManager.cpp
Go to the documentation of this file.
00001 
00007 /*
00008     This file is part of MyGUI.
00009 
00010     MyGUI is free software: you can redistribute it and/or modify
00011     it under the terms of the GNU Lesser General Public License as published by
00012     the Free Software Foundation, either version 3 of the License, or
00013     (at your option) any later version.
00014 
00015     MyGUI is distributed in the hope that it will be useful,
00016     but WITHOUT ANY WARRANTY; without even the implied warranty of
00017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018     GNU Lesser General Public License for more details.
00019 
00020     You should have received a copy of the GNU Lesser General Public License
00021     along with MyGUI.  If not, see <http://www.gnu.org/licenses/>.
00022 */
00023 #include "MyGUI_Precompiled.h"
00024 #include "MyGUI_ResourceManager.h"
00025 #include "MyGUI_LanguageManager.h"
00026 #include "MyGUI_XmlDocument.h"
00027 #include "MyGUI_DataManager.h"
00028 #include "MyGUI_FactoryManager.h"
00029 
00030 namespace MyGUI
00031 {
00032 
00033     const std::string XML_TYPE("Language");
00034 
00035     MYGUI_INSTANCE_IMPLEMENT( LanguageManager )
00036 
00037     void LanguageManager::initialise()
00038     {
00039         MYGUI_ASSERT(!mIsInitialise, INSTANCE_TYPE_NAME << " initialised twice");
00040         MYGUI_LOG(Info, "* Initialise: " << INSTANCE_TYPE_NAME);
00041 
00042         ResourceManager::getInstance().registerLoadXmlDelegate(XML_TYPE) = newDelegate(this, &LanguageManager::_load);
00043 
00044         MYGUI_LOG(Info, INSTANCE_TYPE_NAME << " successfully initialized");
00045         mIsInitialise = true;
00046     }
00047 
00048     void LanguageManager::shutdown()
00049     {
00050         if (!mIsInitialise) return;
00051         MYGUI_LOG(Info, "* Shutdown: " << INSTANCE_TYPE_NAME);
00052 
00053         ResourceManager::getInstance().unregisterLoadXmlDelegate(XML_TYPE);
00054 
00055         MYGUI_LOG(Info, INSTANCE_TYPE_NAME << " successfully shutdown");
00056         mIsInitialise = false;
00057     }
00058 
00059     bool LanguageManager::load(const std::string& _file)
00060     {
00061         return ResourceManager::getInstance()._loadImplement(_file, true, XML_TYPE, INSTANCE_TYPE_NAME);
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         mMapLanguage.clear();
00123 
00124         mCurrentLanguageName = _name;
00125 
00126         MapListString::iterator item = mMapFile.find(_name);
00127         if (item == mMapFile.end())
00128         {
00129             MYGUI_LOG(Error, "Language '" << _name << "' is not found");
00130             return;
00131         }
00132 
00133         for (VectorString::const_iterator iter=item->second.begin(); iter!=item->second.end(); ++iter)
00134         {
00135             loadLanguage(*iter, false);
00136         }
00137 
00138         eventChangeLanguage(mCurrentLanguageName);
00139     }
00140 
00141     bool LanguageManager::loadLanguage(const std::string& _file, bool _user)
00142     {
00143         IDataStream* data = DataManager::getInstance().getData(_file);
00144         if (data == nullptr)
00145         {
00146             MYGUI_LOG(Error, "file '" << _file << "' not found");
00147             return false;
00148         }
00149 
00150         if (_file.find(".xml") != std::string::npos)
00151             _loadLanguageXML(data, _user);
00152         else
00153             _loadLanguage(data, _user);
00154 
00155         delete data;
00156         return true;
00157     }
00158 
00159     void LanguageManager::_loadLanguageXML(IDataStream* _stream, bool _user)
00160     {
00161         xml::Document doc;
00162         // формат xml
00163         if (doc.open(_stream))
00164         {
00165             xml::ElementPtr root = doc.getRoot();
00166             if (root)
00167             {
00168                 xml::ElementEnumerator tag = root->getElementEnumerator();
00169                 while (tag.next("Tag"))
00170                 {
00171                     if (_user)
00172                         mUserMapLanguage[tag->findAttribute("name")] = tag->getContent();
00173                     else
00174                         mMapLanguage[tag->findAttribute("name")] = tag->getContent();
00175                 }
00176             }
00177         }
00178     }
00179 
00180     void LanguageManager::_loadLanguage(IDataStream* _stream, bool _user)
00181     {
00182         // формат txt
00183         std::string read;
00184         while (!_stream->eof())
00185         {
00186             _stream->readline(read, '\n');
00187             if (read.empty()) continue;
00188 
00189             // заголовок утф
00190             if ((uint8)read[0] == 0xEF && read.size() > 2)
00191             {
00192                 read.erase(0, 3);
00193             }
00194 
00195             if (read[read.size()-1] == '\r') read.erase(read.size()-1, 1);
00196             if (read.empty()) continue;
00197 
00198             size_t pos = read.find_first_of(" \t");
00199             if (_user)
00200             {
00201                 if (pos == std::string::npos) mUserMapLanguage[read] = "";
00202                 else mUserMapLanguage[read.substr(0, pos)] = read.substr(pos+1, std::string::npos);
00203             }
00204             else
00205             {
00206                 if (pos == std::string::npos) mMapLanguage[read] = "";
00207                 else mMapLanguage[read.substr(0, pos)] = read.substr(pos+1, std::string::npos);
00208             }
00209         }
00210     }
00211 
00212     UString LanguageManager::replaceTags(const UString& _line)
00213     {
00214         // вот хз, что быстрее, итераторы или математика указателей,
00215         // для непонятно какого размера одного символа UTF8
00216         UString line(_line);
00217 
00218         if (mMapLanguage.empty() && mUserMapLanguage.empty())
00219             return _line;
00220 
00221         UString::iterator end = line.end();
00222         for (UString::iterator iter=line.begin(); iter!=end; )
00223         {
00224             if (*iter == '#')
00225             {
00226                 ++iter;
00227                 if (iter == end)
00228                 {
00229                     return line;
00230                 }
00231                 else
00232                 {
00233                     if (*iter != '{')
00234                     {
00235                         ++iter;
00236                         continue;
00237                     }
00238                     UString::iterator iter2 = iter;
00239                     ++iter2;
00240                     while (true)
00241                     {
00242                         if (iter2 == end) return line;
00243                         if (*iter2 == '}')
00244                         {
00245                             size_t start = iter - line.begin();
00246                             size_t len = (iter2 - line.begin()) - start - 1;
00247                             const UString& tag = line.substr(start + 1, len);
00248 
00249                             bool find = true;
00250                             MapLanguageString::iterator replace = mMapLanguage.find(tag);
00251                             if (replace == mMapLanguage.end())
00252                             {
00253                                 replace = mUserMapLanguage.find(tag);
00254                                 find = replace != mUserMapLanguage.end();
00255                             }
00256 
00257                             if (!find)
00258                             {
00259                                 iter = line.insert(iter, '#') + size_t(len + 2);
00260                                 end = line.end();
00261                                 break;
00262                             }
00263 
00264                             iter = line.erase(iter - size_t(1), iter2 + size_t(1));
00265                             size_t pos = iter - line.begin();
00266                             line.insert(pos, replace->second);
00267                             iter = line.begin() + pos + replace->second.length();
00268                             end = line.end();
00269                             if (iter == end) return line;
00270                             break;
00271 
00272                         }
00273                         ++iter2;
00274                     }
00275                 }
00276             }
00277             else
00278             {
00279                 ++iter;
00280             }
00281         }
00282 
00283         return line;
00284     }
00285 
00286     UString LanguageManager::getTag(const UString& _tag)
00287     {
00288         MapLanguageString::iterator iter = mMapLanguage.find(_tag);
00289         if (iter == mMapLanguage.end())
00290         {
00291             iter = mUserMapLanguage.find(_tag);
00292             if (iter != mUserMapLanguage.end()) return iter->second;
00293             return _tag;
00294         }
00295 
00296         return iter->second;
00297     }
00298 
00299     const std::string& LanguageManager::getCurrentLanguage()
00300     {
00301         return mCurrentLanguageName;
00302     }
00303 
00304     void LanguageManager::addUserTag(const UString& _tag, const UString& _replace)
00305     {
00306         mUserMapLanguage[_tag] = _replace;
00307     }
00308 
00309     void LanguageManager::clearUserTags()
00310     {
00311         mUserMapLanguage.clear();
00312     }
00313 
00314     bool LanguageManager::loadUserTags(const std::string& _file)
00315     {
00316         return loadLanguage(_file, true);
00317     }
00318 
00319 } // namespace MyGUI