summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2017-04-05 19:03:59 +0300
committerAndrei Karas <akaras@inbox.ru>2017-04-05 19:03:59 +0300
commit3b4ffd7199d990d1cbd0e7cbe23fa41f04d38e74 (patch)
treefe7ab920632207462354714e12604e2064d059ea
parentd8a530e299b4dd04c020ca3e3eeda7b12f89b69b (diff)
downloadmanaplus-3b4ffd7199d990d1cbd0e7cbe23fa41f04d38e74.tar.gz
manaplus-3b4ffd7199d990d1cbd0e7cbe23fa41f04d38e74.tar.bz2
manaplus-3b4ffd7199d990d1cbd0e7cbe23fa41f04d38e74.tar.xz
manaplus-3b4ffd7199d990d1cbd0e7cbe23fa41f04d38e74.zip
Add chat command for translate message from player language to english.
Also add po field into languages.xml.
-rw-r--r--src/actions/chat.cpp45
-rw-r--r--src/actions/chat.h1
-rw-r--r--src/being/being.h3
-rw-r--r--src/being/playerinfo.cpp17
-rw-r--r--src/being/playerinfo.h4
-rw-r--r--src/client.cpp4
-rw-r--r--src/dyetool/actions/chat.cpp1
-rw-r--r--src/dyetool/client.cpp2
-rw-r--r--src/enums/input/inputaction.h1
-rw-r--r--src/input/inputactionmap.h6
-rw-r--r--src/net/eathena/beingrecv.cpp2
-rw-r--r--src/resources/db/languagedb.cpp37
-rw-r--r--src/resources/db/languagedb.h2
-rw-r--r--src/utils/langs.cpp25
-rw-r--r--src/utils/langs.h2
-rw-r--r--src/utils/translation/podict.cpp5
-rw-r--r--src/utils/translation/podict.h2
-rw-r--r--src/utils/translation/translationmanager.cpp8
-rw-r--r--src/utils/translation/translationmanager.h2
19 files changed, 163 insertions, 6 deletions
diff --git a/src/actions/chat.cpp b/src/actions/chat.cpp
index 037b25942..4da242569 100644
--- a/src/actions/chat.cpp
+++ b/src/actions/chat.cpp
@@ -49,6 +49,8 @@
#include "utils/booleanoptions.h"
#include "utils/chatutils.h"
+#include "utils/translation/podict.h"
+
#include "debug.h"
const int DEFAULT_CHAT_WINDOW_SCROLL = 7;
@@ -671,4 +673,47 @@ impHandler(guildNotice)
return true;
}
+impHandler(translate)
+{
+ if (reverseDictionary == nullptr ||
+ localPlayer == nullptr ||
+ event.args.empty())
+ {
+ return false;
+ }
+
+ ChatTab *const tab = event.tab;
+ if (tab == nullptr)
+ return false;
+
+ std::string srcStr = event.args;
+ std::string enStr;
+ toLower(srcStr);
+ if (localPlayer->getLanguageId() > 0)
+ {
+ if (reverseDictionary->haveStr(srcStr))
+ enStr = reverseDictionary->getStr(srcStr);
+ else if (dictionary->haveStr(srcStr))
+ enStr = srcStr;
+ }
+ else
+ {
+ if (dictionary->haveStr(srcStr))
+ enStr = srcStr;
+ }
+
+ if (enStr.empty())
+ {
+ tab->chatLog(
+ // TRANSLATORS: translation error message
+ strprintf(_("No translation found for string: %s"),
+ srcStr.c_str()),
+ ChatMsgType::BY_SERVER);
+ return true;
+ }
+
+ tab->chatInput(enStr);
+ return true;
+}
+
} // namespace Actions
diff --git a/src/actions/chat.h b/src/actions/chat.h
index 0794ec9ed..ba33806a3 100644
--- a/src/actions/chat.h
+++ b/src/actions/chat.h
@@ -61,6 +61,7 @@ namespace Actions
decHandler(hat);
decHandler(chatClipboard);
decHandler(guildNotice);
+ decHandler(translate);
} // namespace Actions
#undef decHandler
diff --git a/src/being/being.h b/src/being/being.h
index 0110f3141..79f9a4d83 100644
--- a/src/being/being.h
+++ b/src/being/being.h
@@ -1063,6 +1063,9 @@ class Being notfinal : public ActorSprite,
void setLanguageId(const int lang) restrict2 noexcept2;
+ int getLanguageId() restrict2 noexcept2 A_WARN_UNUSED
+ { return mLanguageId; }
+
uint16_t getTeamId() const restrict2 noexcept2 A_WARN_UNUSED
{ return mTeamId; }
diff --git a/src/being/playerinfo.cpp b/src/being/playerinfo.cpp
index 25620d5ba..8a9c55c5e 100644
--- a/src/being/playerinfo.cpp
+++ b/src/being/playerinfo.cpp
@@ -42,6 +42,8 @@
#include "utils/delete2.h"
+#include "utils/translation/translationmanager.h"
+
#include "debug.h"
namespace PlayerInfo
@@ -64,6 +66,7 @@ BeingId mElementalId = BeingId_zero;
Trading mTrading = Trading_false;
bool mVending = false;
int mLevelProgress = 0;
+int mServerLanguage = -1;
std::set<int> mProtectedItems;
// --- Triggers ---------------------------------------------------------------
@@ -639,4 +642,18 @@ bool isVending()
return mVending;
}
+void setServerLanguage(const int lang)
+{
+ if (lang != mServerLanguage)
+ {
+ mServerLanguage = lang;
+ TranslationManager::loadDictionaryLang();
+ }
+}
+
+int getServerLanguage()
+{
+ return mServerLanguage;
+}
+
} // namespace PlayerInfo
diff --git a/src/being/playerinfo.h b/src/being/playerinfo.h
index 0372bafc4..1c81d7761 100644
--- a/src/being/playerinfo.h
+++ b/src/being/playerinfo.h
@@ -297,6 +297,10 @@ namespace PlayerInfo
void enableVending(const bool b);
bool isVending() A_WARN_UNUSED;
+
+ void setServerLanguage(const int lang);
+
+ int getServerLanguage() A_WARN_UNUSED;
} // namespace PlayerInfo
#endif // BEING_PLAYERINFO_H
diff --git a/src/client.cpp b/src/client.cpp
index 64744e49e..c8530da94 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -432,6 +432,7 @@ void Client::gameInit()
VirtFs::mountDir(settings.localDataDir,
Append_false);
TranslationManager::loadCurrentLang();
+ TranslationManager::loadDictionaryLang();
#ifdef ENABLE_CUSTOMNLS
TranslationManager::loadGettextLang();
#endif // ENABLE_CUSTOMNLS
@@ -1152,6 +1153,7 @@ int Client::gameExec()
_("Connecting to server"),
State::SWITCH_SERVER);
TranslationManager::loadCurrentLang();
+ TranslationManager::loadDictionaryLang();
BLOCK_END("Client::gameExec State::CONNECT_SERVER")
break;
@@ -1218,6 +1220,7 @@ int Client::gameExec()
logger->log1("State: WORLD SELECT");
{
TranslationManager::loadCurrentLang();
+ TranslationManager::loadDictionaryLang();
if (!loginHandler)
{
BLOCK_END("Client::gameExec State::WORLD_SELECT")
@@ -1346,6 +1349,7 @@ int Client::gameExec()
initFeatures();
TranslationManager::loadCurrentLang();
+ TranslationManager::loadDictionaryLang();
PlayerInfo::stateChange(mState);
delete spellManager;
diff --git a/src/dyetool/actions/chat.cpp b/src/dyetool/actions/chat.cpp
index 150f3d7fb..940ded31c 100644
--- a/src/dyetool/actions/chat.cpp
+++ b/src/dyetool/actions/chat.cpp
@@ -61,5 +61,6 @@ impHandlerVoid(chatGuildTab)
impHandlerVoid(hat)
impHandlerVoid(chatClipboard)
impHandlerVoid(guildNotice)
+impHandlerVoid(translate)
} // namespace Actions
diff --git a/src/dyetool/client.cpp b/src/dyetool/client.cpp
index f618db321..cf3fceed6 100644
--- a/src/dyetool/client.cpp
+++ b/src/dyetool/client.cpp
@@ -282,6 +282,7 @@ void Client::gameInit()
VirtFs::mountDir(settings.localDataDir,
Append_false);
TranslationManager::loadCurrentLang();
+ TranslationManager::loadDictionaryLang();
#ifdef ENABLE_CUSTOMNLS
TranslationManager::loadGettextLang();
#endif // ENABLE_CUSTOMNLS
@@ -662,6 +663,7 @@ int Client::gameExec()
paths.setDefaultValues(getPathsDefaults());
initPaths();
TranslationManager::loadCurrentLang();
+ TranslationManager::loadDictionaryLang();
if (desktop)
desktop->reloadWallpaper();
diff --git a/src/enums/input/inputaction.h b/src/enums/input/inputaction.h
index ee5e1781c..b514805b6 100644
--- a/src/enums/input/inputaction.h
+++ b/src/enums/input/inputaction.h
@@ -686,6 +686,7 @@ enumStart(InputAction)
PARTY_AUTO_ITEM_SHARE,
CREATE_ITEM,
COPY_OUTFIT_TO_CHAT,
+ COMMAND_TRANSLATE,
TOTAL
}
enumEnd(InputAction);
diff --git a/src/input/inputactionmap.h b/src/input/inputactionmap.h
index 2301c1728..a717c7e5e 100644
--- a/src/input/inputactionmap.h
+++ b/src/input/inputactionmap.h
@@ -5606,6 +5606,12 @@ static const InputActionData inputActionData
"outfittochat|copyoutfittochat",
UseArgs_false,
Protected_true},
+ {"keyCommandTranslate",
+ defaultAction(&Actions::translate),
+ InputCondition::INGAME,
+ "translate|trans|tran",
+ UseArgs_false,
+ Protected_true},
};
#undef defaultAction
diff --git a/src/net/eathena/beingrecv.cpp b/src/net/eathena/beingrecv.cpp
index 6c78a8f40..52b1508da 100644
--- a/src/net/eathena/beingrecv.cpp
+++ b/src/net/eathena/beingrecv.cpp
@@ -1766,6 +1766,8 @@ void BeingRecv::processBeingAttrs(Net::MessageIn &msg)
dstBeing->setHorse(mount);
}
dstBeing->setLanguageId(language);
+ if (dstBeing == localPlayer)
+ PlayerInfo::setServerLanguage(language);
}
}
diff --git a/src/resources/db/languagedb.cpp b/src/resources/db/languagedb.cpp
index e4bbffea4..b7e3ebc0e 100644
--- a/src/resources/db/languagedb.cpp
+++ b/src/resources/db/languagedb.cpp
@@ -31,7 +31,9 @@
namespace
{
std::string mDefaultIcon;
- std::map<int, std::string> mLanguages;
+ std::string mDefaultPo;
+ std::map<int, std::string> mIcons;
+ std::map<int, std::string> mPo;
} // namespace
void LanguageDb::load()
@@ -74,7 +76,23 @@ void LanguageDb::loadXmlFile(const std::string &fileName,
continue;
}
const std::string icon = XML::getProperty(node, "icon", "");
- mLanguages[id] = icon;
+ const std::string po = XML::getProperty(node, "po", "");
+ if (icon.empty())
+ {
+ reportAlways("LanguageDb: empty icon field");
+ }
+ else
+ {
+ mIcons[id] = icon;
+ }
+ if (po.empty())
+ {
+ reportAlways("LanguageDb: empty po field");
+ }
+ else
+ {
+ mPo[id] = po;
+ }
}
}
@@ -83,13 +101,22 @@ void LanguageDb::loadXmlFile(const std::string &fileName,
void LanguageDb::unload()
{
- mLanguages.clear();
+ mIcons.clear();
+ mPo.clear();
}
const std::string &LanguageDb::getIcon(const int id)
{
- std::map<int, std::string>::const_iterator it = mLanguages.find(id);
- if (it == mLanguages.end())
+ std::map<int, std::string>::const_iterator it = mIcons.find(id);
+ if (it == mIcons.end())
return mDefaultIcon;
return (*it).second;
}
+
+const std::string &LanguageDb::getPo(const int id)
+{
+ std::map<int, std::string>::const_iterator it = mPo.find(id);
+ if (it == mPo.end())
+ return mDefaultPo;
+ return (*it).second;
+}
diff --git a/src/resources/db/languagedb.h b/src/resources/db/languagedb.h
index 18302a451..8f33576a6 100644
--- a/src/resources/db/languagedb.h
+++ b/src/resources/db/languagedb.h
@@ -37,6 +37,8 @@ namespace LanguageDb
void unload();
const std::string &getIcon(const int id);
+
+ const std::string &getPo(const int id);
} // namespace LanguageDB
#endif // RESOURCES_DB_LANGUAGEDB_H
diff --git a/src/utils/langs.cpp b/src/utils/langs.cpp
index 41545ac52..8aa452077 100644
--- a/src/utils/langs.cpp
+++ b/src/utils/langs.cpp
@@ -20,8 +20,16 @@
#include "utils/langs.h"
+#include "logger.h"
+
#include "configuration.h"
+#ifndef DYECMD
+#include "being/playerinfo.h"
+
+#include "resources/db/languagedb.h"
+#endif // DYECMD
+
#include "debug.h"
static const char *getLangName()
@@ -58,6 +66,23 @@ LangVect getLang()
return langs;
}
+LangVect getServerLang()
+{
+ LangVect langs;
+#ifndef DYECMD
+ const int id = PlayerInfo::getServerLanguage();
+ std::string lang = LanguageDb::getPo(id);
+ if (lang.empty())
+ return langs;
+ langs.push_back(lang);
+ const size_t idx = lang.find('_');
+ if (idx != std::string::npos)
+ langs.push_back(lang.substr(0, idx));
+#endif // DYECMD
+
+ return langs;
+}
+
std::string getLangSimple()
{
const std::string lang = config.getStringValue("lang");
diff --git a/src/utils/langs.h b/src/utils/langs.h
index dfbe65995..902dcf264 100644
--- a/src/utils/langs.h
+++ b/src/utils/langs.h
@@ -31,6 +31,8 @@ typedef LangVect::const_iterator LangIter;
LangVect getLang() A_WARN_UNUSED;
+LangVect getServerLang() A_WARN_UNUSED;
+
std::string getLangSimple() A_WARN_UNUSED;
std::string getLangShort() A_WARN_UNUSED;
diff --git a/src/utils/translation/podict.cpp b/src/utils/translation/podict.cpp
index 37b1b2fe8..56fd42467 100644
--- a/src/utils/translation/podict.cpp
+++ b/src/utils/translation/podict.cpp
@@ -54,3 +54,8 @@ const char *PoDict::getChar(const char *const str)
return str;
return mPoLines[str].c_str();
}
+
+bool PoDict::haveStr(const std::string &str) const
+{
+ return mPoLines.find(str) != mPoLines.end();
+}
diff --git a/src/utils/translation/podict.h b/src/utils/translation/podict.h
index a8b18bba4..d40aa1499 100644
--- a/src/utils/translation/podict.h
+++ b/src/utils/translation/podict.h
@@ -41,6 +41,8 @@ class PoDict final
const char *getChar(const char *const str);
+ bool haveStr(const std::string &str) const;
+
#ifndef UNITTESTS
protected:
#endif // UNITTESTS
diff --git a/src/utils/translation/translationmanager.cpp b/src/utils/translation/translationmanager.cpp
index f64d8e612..808ad5f2f 100644
--- a/src/utils/translation/translationmanager.cpp
+++ b/src/utils/translation/translationmanager.cpp
@@ -43,7 +43,13 @@ void TranslationManager::loadCurrentLang()
delete translator;
translator = loadLang(getLang(), "");
translator = loadLang(getLang(), "help/", translator);
- dictionary = loadLang(getLang(), "dict/");
+}
+
+void TranslationManager::loadDictionaryLang()
+{
+ delete dictionary;
+ delete reverseDictionary;
+ dictionary = loadLang(getServerLang(), "dict/");
reverseDictionary = reverseLang(dictionary);
}
diff --git a/src/utils/translation/translationmanager.h b/src/utils/translation/translationmanager.h
index 81ac4fda7..088d97449 100644
--- a/src/utils/translation/translationmanager.h
+++ b/src/utils/translation/translationmanager.h
@@ -43,6 +43,8 @@ class TranslationManager final
static void loadCurrentLang();
+ static void loadDictionaryLang();
+
#ifdef ENABLE_CUSTOMNLS
static void loadGettextLang();
#endif // ENABLE_CUSTOMNLS