diff --git a/src/httprpc.cpp b/src/httprpc.cpp --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -405,8 +405,7 @@ // Same message as AbortNode. uiInterface.ThreadSafeMessageBox( _("Error: A fatal internal error occurred, see debug.log for " - "details") - .translated, + "details"), "", CClientUIInterface::MSG_ERROR); return false; } diff --git a/src/httpserver.cpp b/src/httpserver.cpp --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -179,11 +180,12 @@ LookupSubNet(strAllow.c_str(), subnet); if (!subnet.IsValid()) { uiInterface.ThreadSafeMessageBox( - strprintf("Invalid -rpcallowip subnet specification: %s. " - "Valid are a single IP (e.g. 1.2.3.4), a " - "network/netmask (e.g. 1.2.3.4/255.255.255.0) or a " - "network/CIDR (e.g. 1.2.3.4/24).", - strAllow), + strprintf( + Untranslated("Invalid -rpcallowip subnet specification: " + "%s. Valid are a single IP (e.g. 1.2.3.4), a " + "network/netmask (e.g. 1.2.3.4/255.255.255.0) " + "or a network/CIDR (e.g. 1.2.3.4/24)."), + strAllow), "", CClientUIInterface::MSG_ERROR); return false; } diff --git a/src/index/base.cpp b/src/index/base.cpp --- a/src/index/base.cpp +++ b/src/index/base.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -25,8 +26,9 @@ SetMiscWarning(strMessage); LogPrintf("*** %s\n", strMessage); uiInterface.ThreadSafeMessageBox( - "Error: A fatal internal error occurred, see debug.log for details", "", - CClientUIInterface::MSG_ERROR); + Untranslated("Error: A fatal internal error occurred, see debug.log " + "for details"), + "", CClientUIInterface::MSG_ERROR); StartShutdown(); } diff --git a/src/init.cpp b/src/init.cpp --- a/src/init.cpp +++ b/src/init.cpp @@ -2395,7 +2395,7 @@ bool fLoaded = false; while (!fLoaded && !ShutdownRequested()) { const bool fReset = fReindex; - std::string strLoadError; + bilingual_str strLoadError; uiInterface.InitMessage(_("Loading block index...").translated); do { @@ -2437,7 +2437,7 @@ if (ShutdownRequested()) { break; } - strLoadError = _("Error loading block database").translated; + strLoadError = _("Error loading block database"); break; } @@ -2458,8 +2458,7 @@ strLoadError = _("You need to rebuild the database using -reindex to " "go back to unpruned mode. This will redownload the " - "entire blockchain") - .translated; + "entire blockchain"); break; } @@ -2470,8 +2469,7 @@ // This is called again in ThreadImport after the reindex // completes. if (!fReindex && !LoadGenesisBlock(chainparams)) { - strLoadError = - _("Error initializing block database").translated; + strLoadError = _("Error initializing block database"); break; } @@ -2486,8 +2484,7 @@ ::ChainstateActive().CoinsErrorCatcher().AddReadErrCallback( []() { uiInterface.ThreadSafeMessageBox( - _("Error reading from database, shutting down.") - .translated, + _("Error reading from database, shutting down."), "", CClientUIInterface::MSG_ERROR); }); @@ -2495,8 +2492,7 @@ // This is a no-op if we cleared the coinsviewdb with -reindex // or -reindex-chainstate if (!::ChainstateActive().CoinsDB().Upgrade()) { - strLoadError = - _("Error upgrading chainstate database").translated; + strLoadError = _("Error upgrading chainstate database"); break; } @@ -2505,8 +2501,7 @@ if (!::ChainstateActive().ReplayBlocks(params)) { strLoadError = _("Unable to replay blocks. You will need to rebuild " - "the database using -reindex-chainstate.") - .translated; + "the database using -reindex-chainstate."); break; } @@ -2521,8 +2516,7 @@ // LoadChainTip initializes the chain based on CoinsTip()'s // best block if (!::ChainstateActive().LoadChainTip(chainparams)) { - strLoadError = - _("Error initializing block database").translated; + strLoadError = _("Error initializing block database"); break; } assert(::ChainActive().Tip() != nullptr); @@ -2548,8 +2542,7 @@ "to your computer's date and time being set " "incorrectly. Only rebuild the block database if " "you are sure that your computer's date and time " - "are correct") - .translated; + "are correct"); break; } @@ -2558,14 +2551,13 @@ gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL), gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS))) { - strLoadError = - _("Corrupted block database detected").translated; + strLoadError = _("Corrupted block database detected"); break; } } } catch (const std::exception &e) { LogPrintf("%s\n", e.what()); - strLoadError = _("Error opening block database").translated; + strLoadError = _("Error opening block database"); break; } @@ -2578,11 +2570,11 @@ // first suggest a reindex if (!fReset) { bool fRet = uiInterface.ThreadSafeQuestion( - strLoadError + ".\n\n" + - _("Do you want to rebuild the block database now?") - .translated, - strLoadError + ".\nPlease restart with -reindex or " - "-reindex-chainstate to recover.", + strLoadError + Untranslated(".\n\n") + + _("Do you want to rebuild the block database now?"), + strLoadError.original + + ".\nPlease restart with -reindex or " + "-reindex-chainstate to recover.", "", CClientUIInterface::MSG_ERROR | CClientUIInterface::BTN_ABORT); @@ -2594,7 +2586,7 @@ return false; } } else { - return InitError(strLoadError); + return InitError(strLoadError.translated); } } } diff --git a/src/interfaces/node.h b/src/interfaces/node.h --- a/src/interfaces/node.h +++ b/src/interfaces/node.h @@ -228,14 +228,15 @@ //! Register handler for message box messages. using MessageBoxFn = - std::function; virtual std::unique_ptr handleMessageBox(MessageBoxFn fn) = 0; //! Register handler for question messages. - using QuestionFn = std::function; + using QuestionFn = + std::function; virtual std::unique_ptr handleQuestion(QuestionFn fn) = 0; //! Register handler for progress messages. diff --git a/src/net.h b/src/net.h --- a/src/net.h +++ b/src/net.h @@ -40,6 +40,7 @@ class Config; class CNode; class CScheduler; +struct bilingual_str; /** Default for -whitelistrelay. */ static const bool DEFAULT_WHITELISTRELAY = true; @@ -363,7 +364,7 @@ NetPermissionFlags m_permissions; }; - bool BindListenPort(const CService &bindAddr, std::string &strError, + bool BindListenPort(const CService &bindAddr, bilingual_str &strError, NetPermissionFlags permissions); bool Bind(const CService &addr, unsigned int flags, NetPermissionFlags permissions); diff --git a/src/net.cpp b/src/net.cpp --- a/src/net.cpp +++ b/src/net.cpp @@ -2208,27 +2208,28 @@ } } -bool CConnman::BindListenPort(const CService &addrBind, std::string &strError, +bool CConnman::BindListenPort(const CService &addrBind, bilingual_str &strError, NetPermissionFlags permissions) { - strError = ""; int nOne = 1; // Create socket for listening for incoming connections struct sockaddr_storage sockaddr; socklen_t len = sizeof(sockaddr); if (!addrBind.GetSockAddr((struct sockaddr *)&sockaddr, &len)) { - strError = strprintf("Error: Bind address family for %s not supported", - addrBind.ToString()); - LogPrintf("%s\n", strError); + strError = strprintf( + Untranslated("Error: Bind address family for %s not supported"), + addrBind.ToString()); + LogPrintf("%s\n", strError.original); return false; } SOCKET hListenSocket = CreateSocket(addrBind); if (hListenSocket == INVALID_SOCKET) { - strError = strprintf("Error: Couldn't open socket for incoming " - "connections (socket returned error %s)", - NetworkErrorString(WSAGetLastError())); - LogPrintf("%s\n", strError); + strError = + strprintf(Untranslated("Error: Couldn't open socket for incoming " + "connections (socket returned error %s)"), + NetworkErrorString(WSAGetLastError())); + LogPrintf("%s\n", strError.original); return false; } @@ -2257,16 +2258,14 @@ int nErr = WSAGetLastError(); if (nErr == WSAEADDRINUSE) { strError = strprintf(_("Unable to bind to %s on this computer. %s " - "is probably already running.") - .translated, + "is probably already running."), addrBind.ToString(), PACKAGE_NAME); } else { strError = strprintf(_("Unable to bind to %s on this computer " - "(bind returned error %s)") - .translated, + "(bind returned error %s)"), addrBind.ToString(), NetworkErrorString(nErr)); } - LogPrintf("%s\n", strError); + LogPrintf("%s\n", strError.original); CloseSocket(hListenSocket); return false; } @@ -2275,10 +2274,9 @@ // Listen for incoming connections if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR) { strError = strprintf(_("Error: Listening for incoming connections " - "failed (listen returned error %s)") - .translated, + "failed (listen returned error %s)"), NetworkErrorString(WSAGetLastError())); - LogPrintf("%s\n", strError); + LogPrintf("%s\n", strError.original); CloseSocket(hListenSocket); return false; } @@ -2373,7 +2371,7 @@ if (!(flags & BF_EXPLICIT) && !IsReachable(addr)) { return false; } - std::string strError; + bilingual_str strError; if (!BindListenPort(addr, strError, permissions)) { if ((flags & BF_REPORT_ERROR) && clientInterface) { clientInterface->ThreadSafeMessageBox( @@ -2427,8 +2425,7 @@ if (clientInterface) { clientInterface->ThreadSafeMessageBox( _("Failed to listen on any port. Use -listen=0 if you want " - "this.") - .translated, + "this."), "", CClientUIInterface::MSG_ERROR); } return false; @@ -2508,8 +2505,7 @@ if (clientInterface) { clientInterface->ThreadSafeMessageBox( _("Cannot provide specific connections and have addrman find " - "outgoing connections at the same.") - .translated, + "outgoing connections at the same."), "", CClientUIInterface::MSG_ERROR); } return false; diff --git a/src/noui.h b/src/noui.h --- a/src/noui.h +++ b/src/noui.h @@ -7,12 +7,14 @@ #include +struct bilingual_str; + /** Non-GUI handler, which logs and prints messages. */ -bool noui_ThreadSafeMessageBox(const std::string &message, +bool noui_ThreadSafeMessageBox(const bilingual_str &message, const std::string &caption, unsigned int style); /** Non-GUI handler, which logs and prints questions. */ bool noui_ThreadSafeQuestion( - const std::string & /* ignored interactive message */, + const bilingual_str & /* ignored interactive message */, const std::string &message, const std::string &caption, unsigned int style); /** Non-GUI handler, which only logs a message. */ void noui_InitMessage(const std::string &message); diff --git a/src/noui.cpp b/src/noui.cpp --- a/src/noui.cpp +++ b/src/noui.cpp @@ -5,8 +5,8 @@ #include +#include #include -#include #include #include @@ -17,7 +17,7 @@ boost::signals2::connection noui_ThreadSafeQuestionConn; boost::signals2::connection noui_InitMessageConn; -bool noui_ThreadSafeMessageBox(const std::string &message, +bool noui_ThreadSafeMessageBox(const bilingual_str &message, const std::string &caption, unsigned int style) { bool fSecure = style & CClientUIInterface::SECURE; style &= ~CClientUIInterface::SECURE; @@ -43,17 +43,17 @@ } if (!fSecure) { - LogPrintf("%s%s\n", strCaption, message); + LogPrintf("%s%s\n", strCaption, message.original); } - tfm::format(std::cerr, "%s%s\n", strCaption.c_str(), message.c_str()); + tfm::format(std::cerr, "%s%s\n", strCaption, message.original); return false; } bool noui_ThreadSafeQuestion( - const std::string & /* ignored interactive message */, + const bilingual_str & /* ignored interactive message */, const std::string &message, const std::string &caption, unsigned int style) { - return noui_ThreadSafeMessageBox(message, caption, style); + return noui_ThreadSafeMessageBox(Untranslated(message), caption, style); } void noui_InitMessage(const std::string &message) { @@ -68,15 +68,15 @@ noui_InitMessageConn = uiInterface.InitMessage_connect(noui_InitMessage); } -bool noui_ThreadSafeMessageBoxRedirect(const std::string &message, +bool noui_ThreadSafeMessageBoxRedirect(const bilingual_str &message, const std::string &caption, unsigned int style) { - LogPrintf("%s: %s\n", caption, message); + LogPrintf("%s: %s\n", caption, message.original); return false; } bool noui_ThreadSafeQuestionRedirect( - const std::string & /* ignored interactive message */, + const bilingual_str & /* ignored interactive message */, const std::string &message, const std::string &caption, unsigned int style) { LogPrintf("%s: %s\n", caption, message); diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -33,6 +33,7 @@ #endif // ENABLE_WALLET #include #include +#include #include #include @@ -1507,7 +1508,7 @@ } } -static bool ThreadSafeMessageBox(BitcoinGUI *gui, const std::string &message, +static bool ThreadSafeMessageBox(BitcoinGUI *gui, const bilingual_str &message, const std::string &caption, unsigned int style) { bool modal = (style & CClientUIInterface::MODAL); @@ -1515,14 +1516,22 @@ // bool secure = (style & CClientUIInterface::SECURE); style &= ~CClientUIInterface::SECURE; bool ret = false; + // This is original message, in English, for googling and referencing. + QString detailed_message; + if (message.original != message.translated) { + detailed_message = BitcoinGUI::tr("Original message:") + "\n" + + QString::fromStdString(message.original); + } + // In case of modal message, use blocking connection to wait for user to // click a button bool invoked = QMetaObject::invokeMethod( gui, "message", modal ? GUIUtil::blockingGUIThreadConnection() : Qt::QueuedConnection, Q_ARG(QString, QString::fromStdString(caption)), - Q_ARG(QString, QString::fromStdString(message)), - Q_ARG(unsigned int, style), Q_ARG(bool *, &ret)); + Q_ARG(QString, QString::fromStdString(message.translated)), + Q_ARG(unsigned int, style), Q_ARG(bool *, &ret), + Q_ARG(QString, detailed_message)); assert(invoked); return ret; } diff --git a/src/timedata.cpp b/src/timedata.cpp --- a/src/timedata.cpp +++ b/src/timedata.cpp @@ -102,13 +102,12 @@ if (!fMatch) { fDone = true; - std::string strMessage = + bilingual_str strMessage = strprintf(_("Please check that your computer's date " "and time are correct! If your clock is " - "wrong, %s will not work properly.") - .translated, + "wrong, %s will not work properly."), PACKAGE_NAME); - SetMiscWarning(strMessage); + SetMiscWarning(strMessage.translated); uiInterface.ThreadSafeMessageBox( strMessage, "", CClientUIInterface::MSG_WARNING); } diff --git a/src/ui_interface.h b/src/ui_interface.h --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -11,6 +11,8 @@ #include class CBlockIndex; +struct bilingual_str; + namespace boost { namespace signals2 { class connection; @@ -82,9 +84,11 @@ boost::signals2::connection signal_name##_connect( \ std::function fn); - /** Show message box. */ + /** + * Show message box. + */ ADD_SIGNALS_DECL_WRAPPER(ThreadSafeMessageBox, bool, - const std::string &message, + const bilingual_str &message, const std::string &caption, unsigned int style); /** @@ -93,7 +97,7 @@ * false. */ ADD_SIGNALS_DECL_WRAPPER(ThreadSafeQuestion, bool, - const std::string &message, + const bilingual_str &message, const std::string &noninteractive_message, const std::string &caption, unsigned int style); diff --git a/src/ui_interface.cpp b/src/ui_interface.cpp --- a/src/ui_interface.cpp +++ b/src/ui_interface.cpp @@ -4,6 +4,8 @@ #include +#include + #include #include @@ -50,13 +52,13 @@ ADD_SIGNALS_IMPL_WRAPPER(NotifyHeaderTip); ADD_SIGNALS_IMPL_WRAPPER(BannedListChanged); -bool CClientUIInterface::ThreadSafeMessageBox(const std::string &message, +bool CClientUIInterface::ThreadSafeMessageBox(const bilingual_str &message, const std::string &caption, unsigned int style) { return g_ui_signals.ThreadSafeMessageBox(message, caption, style); } bool CClientUIInterface::ThreadSafeQuestion( - const std::string &message, const std::string &non_interactive_message, + const bilingual_str &message, const std::string &non_interactive_message, const std::string &caption, unsigned int style) { return g_ui_signals.ThreadSafeQuestion(message, non_interactive_message, caption, style); @@ -88,10 +90,12 @@ } bool InitError(const std::string &str) { - uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_ERROR); + uiInterface.ThreadSafeMessageBox(Untranslated(str), "", + CClientUIInterface::MSG_ERROR); return false; } void InitWarning(const std::string &str) { - uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_WARNING); + uiInterface.ThreadSafeMessageBox(Untranslated(str), "", + CClientUIInterface::MSG_WARNING); } diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1173,13 +1173,13 @@ SetMiscWarning(strMessage); LogPrintf("*** %s\n", strMessage); if (!userMessage.empty()) { - uiInterface.ThreadSafeMessageBox( - userMessage, "", CClientUIInterface::MSG_ERROR | prefix); + uiInterface.ThreadSafeMessageBox(Untranslated(userMessage), "", + CClientUIInterface::MSG_ERROR | + prefix); } else { uiInterface.ThreadSafeMessageBox( _("Error: A fatal internal error occurred, see debug.log for " - "details") - .translated, + "details"), "", CClientUIInterface::MSG_ERROR | CClientUIInterface::MSG_NOPREFIX); }