diff options
author | Andrei Karas <akaras@inbox.ru> | 2012-02-03 15:53:55 +0300 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2012-02-05 22:53:59 +0300 |
commit | bf435a79408d89072f5872ab98449949a8a077b0 (patch) | |
tree | e50bddcd239de2756780691cabf8779dd5efcc12 | |
parent | 42990fcd0a9f662eea267097e88b68b9c30da457 (diff) | |
download | mv-bf435a79408d89072f5872ab98449949a8a077b0.tar.gz mv-bf435a79408d89072f5872ab98449949a8a077b0.tar.bz2 mv-bf435a79408d89072f5872ab98449949a8a077b0.tar.xz mv-bf435a79408d89072f5872ab98449949a8a077b0.zip |
Add own translation system.
-rw-r--r-- | src/CMakeLists.txt | 6 | ||||
-rw-r--r-- | src/Makefile.am | 6 | ||||
-rw-r--r-- | src/client.cpp | 5 | ||||
-rw-r--r-- | src/game.cpp | 2 | ||||
-rw-r--r-- | src/utils/langs.h | 3 | ||||
-rw-r--r-- | src/utils/stringutils.cpp | 7 | ||||
-rw-r--r-- | src/utils/stringutils.h | 2 | ||||
-rw-r--r-- | src/utils/translation/podict.cpp | 55 | ||||
-rw-r--r-- | src/utils/translation/podict.h | 59 | ||||
-rw-r--r-- | src/utils/translation/poparser.cpp | 221 | ||||
-rw-r--r-- | src/utils/translation/poparser.h | 78 | ||||
-rw-r--r-- | src/utils/translation/translationmanager.cpp | 72 | ||||
-rw-r--r-- | src/utils/translation/translationmanager.h | 39 | ||||
-rw-r--r-- | src/utils/xml.cpp | 12 | ||||
-rw-r--r-- | src/utils/xml.h | 6 |
15 files changed, 573 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 96c1eac67..3289aed66 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -443,6 +443,12 @@ SET(SRCS resources/spritedef.cpp resources/wallpaper.cpp resources/wallpaper.h + utils/translation/podict.cpp + utils/translation/podict.h + utils/translation/poparser.cpp + utils/translation/poparser.h + utils/translation/translationmanager.cpp + utils/translation/translationmanager.h utils/base64.cpp utils/base64.h utils/checkutils.cpp diff --git a/src/Makefile.am b/src/Makefile.am index e9af09463..204c21bfc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -448,6 +448,12 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \ resources/spritedef.cpp \ resources/wallpaper.cpp \ resources/wallpaper.h \ + utils/translation/podict.cpp \ + utils/translation/podict.h \ + utils/translation/poparser.cpp \ + utils/translation/poparser.h \ + utils/translation/translationmanager.cpp \ + utils/translation/translationmanager.h \ utils/base64.cpp \ utils/base64.h \ utils/checkutils.cpp \ diff --git a/src/client.cpp b/src/client.cpp index c21194834..cb65c3b60 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -101,6 +101,8 @@ #include "utils/paths.h" #include "utils/stringutils.h" +#include "utils/translation/translationmanager.h" + #include "test/testlauncher.h" #include "test/testmain.h" @@ -458,6 +460,8 @@ void Client::gameInit() //resman->selectSkin(); + TranslationManager::loadCurrentLang(); + std::string iconFile = branding.getValue("appIcon", "icons/manaplus"); #ifdef WIN32 iconFile += ".ico"; @@ -1050,6 +1054,7 @@ int Client::gameExec() logger->log1("State: CONNECT SERVER"); mCurrentDialog = new ConnectionDialog( _("Connecting to server"), STATE_SWITCH_SERVER); + TranslationManager::loadCurrentLang(); break; case STATE_LOGIN: diff --git a/src/game.cpp b/src/game.cpp index 0d5c1113e..cd54f9c98 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -104,6 +104,8 @@ #include "utils/gettext.h" #include "utils/mkdir.h" +#include "utils/translation/translationmanager.h" + #include <guichan/exception.hpp> #include <guichan/focushandler.hpp> diff --git a/src/utils/langs.h b/src/utils/langs.h index c3f2f1398..3b9f49f71 100644 --- a/src/utils/langs.h +++ b/src/utils/langs.h @@ -29,6 +29,9 @@ #include <set> #include <vector> +typedef std::vector<std::string> LangVect; +typedef LangVect::const_iterator LangIter; + std::vector<std::string> getLang(); std::string getLangSimple(); diff --git a/src/utils/stringutils.cpp b/src/utils/stringutils.cpp index 16542526f..becb2124d 100644 --- a/src/utils/stringutils.cpp +++ b/src/utils/stringutils.cpp @@ -592,3 +592,10 @@ std::string &removeProtocol(std::string &url) url = url.substr(i + 3); return url; } + +bool strStartWith(std::string str1, std::string str2) +{ + if (str1.size() < str2.size()) + return false; + return str1.substr(0, str2.size()) == str2; +} diff --git a/src/utils/stringutils.h b/src/utils/stringutils.h index 7b512b081..398737179 100644 --- a/src/utils/stringutils.h +++ b/src/utils/stringutils.h @@ -204,4 +204,6 @@ bool findCutFirst(std::string &str1, std::string str2); std::string &removeProtocol(std::string &url); +bool strStartWith(std::string str, std::string start); + #endif // UTILS_STRINGUTILS_H diff --git a/src/utils/translation/podict.cpp b/src/utils/translation/podict.cpp new file mode 100644 index 000000000..0be0b279f --- /dev/null +++ b/src/utils/translation/podict.cpp @@ -0,0 +1,55 @@ +/* + * The ManaPlus Client + * Copyright (C) 2012 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "utils/translation/podict.h" + +#include <string.h> + +#include "localconsts.h" +#include "logger.h" + +#include "debug.h" + +std::string empty; + +PoDict *translator = nullptr; + +PoDict::PoDict(std::string lang) : + mLang(lang) +{ +} + +PoDict::~PoDict() +{ +} + +const std::string PoDict::getStr(std::string &str) +{ + if (mPoLines.find(str) == mPoLines.end()) + return str; + return mPoLines[str]; +} + +const char *PoDict::getChar(const char *str) +{ + if (mPoLines.find(str) == mPoLines.end()) + return str; + return mPoLines[str].c_str(); +} diff --git a/src/utils/translation/podict.h b/src/utils/translation/podict.h new file mode 100644 index 000000000..0b7dd726c --- /dev/null +++ b/src/utils/translation/podict.h @@ -0,0 +1,59 @@ +/* + * The ManaPlus Client + * Copyright (C) 2012 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef UTILS_TRANSLATION_PODICT_H +#define UTILS_TRANSLATION_PODICT_H + +#include <string> +#include <map> + +typedef std::map <std::string, std::string> PoMap; + +class PoDict +{ + public: + PoDict(std::string lang); + + ~PoDict(); + + const std::string getStr(std::string &str); + + const char *getChar(const char *str); + + protected: + friend class PoParser; + + PoMap *getMap() + { return &mPoLines; } + + void set(std::string key, std::string value) + { mPoLines[key] = value; } + + void setLang(std::string lang) + { mLang = lang; } + + private: + PoMap mPoLines; + std::string mLang; +}; + +extern PoDict *translator; + +#endif // UTILS_TRANSLATION_PODICT_H diff --git a/src/utils/translation/poparser.cpp b/src/utils/translation/poparser.cpp new file mode 100644 index 000000000..24d2ee4d4 --- /dev/null +++ b/src/utils/translation/poparser.cpp @@ -0,0 +1,221 @@ +/* + * The ManaPlus Client + * Copyright (C) 2012 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "utils/translation/poparser.h" + +#include "resources/resourcemanager.h" + +#include "utils/stringutils.h" + +#include "localconsts.h" +#include "logger.h" + +#include <string.h> +#include <stdlib.h> + +#include "debug.h" + +PoParser::PoParser() : + mDict(nullptr), + mReadingId(false), + mReadingStr(false) +{ +} + +void PoParser::openFile() +{ + ResourceManager *resman = ResourceManager::getInstance(); + int size; + char *buf = static_cast<char*>(resman->loadFile(getFileName(mLang), size)); + + mFile.str(std::string(buf, size)); + free(buf); +} + +PoDict *PoParser::load(std::string lang) +{ + setLang(lang); + mDict = getDict(); + + openFile(); + + mMsgId = ""; + mMsgStr = ""; + + // cycle by msgid+msgstr + while (readLine()) + { + // reading msgid + while (readMsgId()) + { + if (!readLine()) + break; + } + + if (!mMsgId.empty()) + { + // if we got msgid then reading msgstr + while (readMsgStr()) + { + if (!readLine()) + break; + } + } + + if (!mMsgId.empty() && !mMsgStr.empty()) + { +// logger->log("add key: " + mMsgId); +// logger->log("add value: " + mMsgStr); + + // store key and value + mDict->set(mMsgId, mMsgStr); + } + + mMsgId = ""; + mMsgStr = ""; + } + + return mDict; +} + +bool PoParser::readLine() +{ + char line[1001]; + if (!mFile.getline(line, 1000)) + return false; + mLine = line; + return true; +} + +bool PoParser::readMsgId() +{ + // if we reading msgstr then stop here + if (mReadingStr) + return false; + + const std::string msgId1 = "msgid \""; + + // check if in reading process + if (mReadingId) + { + // if we get empty line in file then stop reading + if (mLine.empty()) + { + mReadingId = false; + return false; + } + else if (checkLine()) + { + // reading text from: "text" + mMsgId += mLine.substr(1, mLine.size() - 2); + mLine = ""; + return true; + } + // stop reading in other case + mReadingId = false; + return false; + } + else + { + // check line start from msgid " + if (strStartWith(mLine, msgId1)) + { + mReadingId = true; + // reading text from: msgid "text" + mMsgId += mLine.substr(msgId1.size(), + mLine.size() - 1 - msgId1.size()); + mLine = ""; + return true; + } + // stop reading if we dont read msgid before + return mMsgId.empty(); + } +} + +bool PoParser::readMsgStr() +{ + const std::string msgStr1 = "msgstr \""; + + // check if in reading process + if (mReadingStr) + { + // if we get empty line in file then stop reading + if (mLine.empty()) + { + mReadingStr = false; + return false; + } + if (checkLine()) + { + // reading text from: "text" + mMsgStr += mLine.substr(1, mLine.size() - 2); + mLine = ""; + return true; + } + // stop reading in other case + mReadingStr = false; + } + else + { + // check line start from msgstr " + if (strStartWith(mLine, msgStr1)) + { + mReadingStr = true; + // reading text from: msgid "text" + mMsgStr += mLine.substr(msgStr1.size(), + mLine.size() - 1 - msgStr1.size()); + mLine = ""; + return true; + } + } + + // stop reading in other case + return false; +} + +bool PoParser::checkLine() +{ + // check is line in format: "text" + return mLine.size() > 2 && mLine[0] == '\"' + && mLine[mLine.size() - 1] == '\"'; +} + +PoDict *PoParser::getEmptyDict() +{ + return new PoDict(""); +} + +bool PoParser::checkLang(std::string lang) const +{ + // check is po file exists + ResourceManager *resman = ResourceManager::getInstance(); + return resman->exists(getFileName(lang)); +} + +std::string PoParser::getFileName(std::string lang) const +{ + // get po file name from lang name + return strprintf("translations/%s.po", lang.c_str()); +} + +PoDict *PoParser::getDict() +{ + return new PoDict(mLang); +} diff --git a/src/utils/translation/poparser.h b/src/utils/translation/poparser.h new file mode 100644 index 000000000..799cd2fe7 --- /dev/null +++ b/src/utils/translation/poparser.h @@ -0,0 +1,78 @@ +/* + * The ManaPlus Client + * Copyright (C) 2012 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef UTILS_TRANSLATION_POPARSER_H +#define UTILS_TRANSLATION_POPARSER_H + +#include "utils/translation/podict.h" + +#include <sstream> +#include <string> + +class PoParser +{ + public: + PoParser(); + + PoDict *load(std::string fileName); + + bool checkLang(std::string lang) const; + + static PoDict *getEmptyDict(); + + private: + void setLang(std::string lang) + { mLang = lang; } + + void openFile(); + + bool readLine(); + + bool readMsgId(); + + bool readMsgStr(); + + bool checkLine(); + + std::string getFileName(std::string lang) const; + + PoDict *getDict(); + + // current lang + std::string mLang; + + // po file object + std::istringstream mFile; + + // current line from po file + std::string mLine; + + std::string mMsgId; + + std::string mMsgStr; + + PoDict *mDict; + + bool mReadingId; + + bool mReadingStr; +}; + +#endif // UTILS_TRANSLATION_POPARSER_H diff --git a/src/utils/translation/translationmanager.cpp b/src/utils/translation/translationmanager.cpp new file mode 100644 index 000000000..b4ae0d949 --- /dev/null +++ b/src/utils/translation/translationmanager.cpp @@ -0,0 +1,72 @@ +/* + * The ManaPlus Client + * Copyright (C) 2012 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "utils/translation/translationmanager.h" + +#include "utils/langs.h" + +#include "utils/translation/podict.h" +#include "utils/translation/poparser.h" + +#include <string.h> + +#include "localconsts.h" +#include "logger.h" + +#include "debug.h" + +void TranslationManager::init() +{ + if (translator) + delete translator; + translator = PoParser::getEmptyDict(); +} + +void TranslationManager::loadCurrentLang() +{ + if (translator) + delete translator; + translator = loadLang(getLang()); +} + +PoDict *TranslationManager::loadLang(LangVect lang) +{ + std::string name = ""; + PoParser parser; + + LangIter it = lang.begin(); + LangIter it_end = lang.end(); + + for (; it != it_end; ++ it) + { + if (*it == "C") + continue; + + if (parser.checkLang(*it)) + { + name = *it; + break; + } + } + if (!name.empty()) + return parser.load(name); + logger->log("can't find client data translation"); + return PoParser::getEmptyDict(); +} diff --git a/src/utils/translation/translationmanager.h b/src/utils/translation/translationmanager.h new file mode 100644 index 000000000..de3875b0a --- /dev/null +++ b/src/utils/translation/translationmanager.h @@ -0,0 +1,39 @@ +/* + * The ManaPlus Client + * Copyright (C) 2012 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef UTILS_TRANSLATION_MANAGER_H +#define UTILS_TRANSLATION_MANAGER_H + +#include <string> +#include <vector> + +class PoDict; + +class TranslationManager +{ + public: + static PoDict *loadLang(std::vector<std::string> lang); + + static void init(); + + static void loadCurrentLang(); +}; + +#endif // UTILS_TRANSLATION_MANAGER_H diff --git a/src/utils/xml.cpp b/src/utils/xml.cpp index 420915d8f..140da72df 100644 --- a/src/utils/xml.cpp +++ b/src/utils/xml.cpp @@ -26,6 +26,8 @@ #include "resources/resourcemanager.h" +#include "utils/translation/podict.h" + #include <iostream> #include <fstream> #include <cstring> @@ -148,6 +150,16 @@ namespace XML return def; } + std::string langProperty(XmlNodePtr node, const char *name, + const std::string &def) + { + std::string str = getProperty(node, name, def); + if (!translator) + return str; + + return translator->getStr(str); + } + bool getBoolProperty(XmlNodePtr node, const char* name, bool def) { xmlChar *prop = xmlGetProp(node, BAD_CAST name); diff --git a/src/utils/xml.h b/src/utils/xml.h index f623fa618..eb5ee88b0 100644 --- a/src/utils/xml.h +++ b/src/utils/xml.h @@ -92,6 +92,12 @@ namespace XML const std::string &def); /** + * Gets a translated string property from an XmlNodePtr. + */ + std::string langProperty(XmlNodePtr node, const char *name, + const std::string &def); + + /** * Gets a boolean property from an XmlNodePtr. */ bool getBoolProperty(XmlNodePtr node, const char *name, bool def); |