From bf435a79408d89072f5872ab98449949a8a077b0 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Fri, 3 Feb 2012 15:53:55 +0300 Subject: Add own translation system. --- src/utils/langs.h | 3 + src/utils/stringutils.cpp | 7 + src/utils/stringutils.h | 2 + src/utils/translation/podict.cpp | 55 +++++++ src/utils/translation/podict.h | 59 +++++++ src/utils/translation/poparser.cpp | 221 +++++++++++++++++++++++++++ src/utils/translation/poparser.h | 78 ++++++++++ src/utils/translation/translationmanager.cpp | 72 +++++++++ src/utils/translation/translationmanager.h | 39 +++++ src/utils/xml.cpp | 12 ++ src/utils/xml.h | 6 + 11 files changed, 554 insertions(+) create mode 100644 src/utils/translation/podict.cpp create mode 100644 src/utils/translation/podict.h create mode 100644 src/utils/translation/poparser.cpp create mode 100644 src/utils/translation/poparser.h create mode 100644 src/utils/translation/translationmanager.cpp create mode 100644 src/utils/translation/translationmanager.h (limited to 'src/utils') 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 #include +typedef std::vector LangVect; +typedef LangVect::const_iterator LangIter; + std::vector 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 . + */ + +#include "utils/translation/podict.h" + +#include + +#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 . + */ + +#ifndef UTILS_TRANSLATION_PODICT_H +#define UTILS_TRANSLATION_PODICT_H + +#include +#include + +typedef std::map 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 . + */ + +#include "utils/translation/poparser.h" + +#include "resources/resourcemanager.h" + +#include "utils/stringutils.h" + +#include "localconsts.h" +#include "logger.h" + +#include +#include + +#include "debug.h" + +PoParser::PoParser() : + mDict(nullptr), + mReadingId(false), + mReadingStr(false) +{ +} + +void PoParser::openFile() +{ + ResourceManager *resman = ResourceManager::getInstance(); + int size; + char *buf = static_cast(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 . + */ + +#ifndef UTILS_TRANSLATION_POPARSER_H +#define UTILS_TRANSLATION_POPARSER_H + +#include "utils/translation/podict.h" + +#include +#include + +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 . + */ + +#include "utils/translation/translationmanager.h" + +#include "utils/langs.h" + +#include "utils/translation/podict.h" +#include "utils/translation/poparser.h" + +#include + +#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 . + */ + +#ifndef UTILS_TRANSLATION_MANAGER_H +#define UTILS_TRANSLATION_MANAGER_H + +#include +#include + +class PoDict; + +class TranslationManager +{ + public: + static PoDict *loadLang(std::vector 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 #include #include @@ -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 @@ -91,6 +91,12 @@ namespace XML std::string getProperty(XmlNodePtr node, const char *name, 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. */ -- cgit v1.2.3-70-g09d2