From af00598c9a5a6d5a87758319a35f7472d1a7c837 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Fri, 8 May 2020 12:17:47 -0400 Subject: [PATCH 01/11] Merge #16224: gui: Bilingual GUI error messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 18bd83b1fee2eb47ed4ad05c91f2d6cc311fc9ad util: Cleanup translation.h (Hennadii Stepanov) e95e658b8ec6e02229691a1941d688e96d4df6af doc: Do not translate technical or extremely rare errors (Hennadii Stepanov) 7e923d47ba9891856b86bc9f718cf2f1f773bdf6 Make InitError bilingual (Hennadii Stepanov) 917ca93553917251e0fd59717a347c63cdfd8a14 Make ThreadSafe{MessageBox|Question} bilingual (Hennadii Stepanov) 23b9fa2e5ec0425980301d2eebad81e660a5ea39 gui: Add detailed text to BitcoinGUI::message (Hennadii Stepanov) Pull request description: This is an alternative to #15340 (it works with the `Chain` interface; see: https://github.com/bitcoin/bitcoin/pull/15340#issuecomment-502674004). Refs: - #16218 (partial fix) - https://github.com/bitcoin/bitcoin/pull/15894#issuecomment-487947077 This PR: - makes GUI error messages bilingual: user's native language + untranslated (i.e. English) - insures that only untranslated messages are written to the debug log file and to `stderr` (that is not the case on master). If a translated string is unavailable only an English string appears to a user. Here are some **examples** (updated): ![Screenshot from 2020-04-24 17-08-37](https://user-images.githubusercontent.com/32963518/80222043-e2458780-864e-11ea-83fc-197b7121dba5.png) ![Screenshot from 2020-04-24 17-12-17](https://user-images.githubusercontent.com/32963518/80222051-e5407800-864e-11ea-92f7-dfef1144becd.png) * `qt5ct: using qt5ct plugin` message is my local environment specific; please ignore it. --- Note for reviewers: `InitWarning()` is out of this PR scope. ACKs for top commit: Sjors: re-tACK 18bd83b1fee2eb47ed4ad05c91f2d6cc311fc9ad MarcoFalke: ACK 18bd83b1fee2eb47ed4ad05c91f2d6cc311fc9ad 🐦 Tree-SHA512: 3cc8ec44f84403e54b57d11714c86b0855ed90eb794b5472e432005073354b9e3f7b4e8e7bf347a4c21be47299dbc7170f2d0c4b80e308205ff09596e55a4f96 # Conflicts: # src/dashd.cpp # src/httpserver.cpp # src/index/base.cpp # src/init.cpp # src/interfaces/chain.cpp # src/interfaces/chain.h # src/interfaces/node.cpp # src/net.h # src/qt/bitcoingui.cpp # src/ui_interface.h # src/wallet/init.cpp # src/wallet/load.cpp --- doc/translation_strings_policy.md | 3 +- src/dashd.cpp | 14 +-- src/httprpc.cpp | 2 +- src/httpserver.cpp | 9 +- src/index/base.cpp | 3 +- src/init.cpp | 183 +++++++++++++++--------------- src/interfaces/chain.cpp | 2 +- src/interfaces/chain.h | 3 +- src/interfaces/node.cpp | 3 +- src/interfaces/node.h | 4 +- src/net.cpp | 35 +++--- src/net.h | 5 +- src/noui.cpp | 19 ++-- src/noui.h | 6 +- src/qt/bitcoingui.cpp | 17 ++- src/qt/bitcoingui.h | 13 ++- src/timedata.cpp | 4 +- src/ui_interface.cpp | 11 +- src/ui_interface.h | 10 +- src/util/translation.h | 6 +- src/validation.cpp | 5 +- src/wallet/init.cpp | 12 +- src/wallet/load.cpp | 12 +- 23 files changed, 202 insertions(+), 179 deletions(-) diff --git a/doc/translation_strings_policy.md b/doc/translation_strings_policy.md index b13ce3c47bd1..45216cb254b0 100644 --- a/doc/translation_strings_policy.md +++ b/doc/translation_strings_policy.md @@ -23,7 +23,8 @@ On a high level, these strings are to be translated: ### GUI strings -Anything that appears to the user in the GUI is to be translated. This includes labels, menu items, button texts, tooltips and window titles. +Do not translate technical or extremely rare errors. +Anything else that appears to the user in the GUI is to be translated. This includes labels, menu items, button texts, tooltips and window titles. This includes messages passed to the GUI through the UI interface through `InitMessage`, `ThreadSafeMessageBox` or `ShowProgress`. General recommendations diff --git a/src/dashd.cpp b/src/dashd.cpp index ddeed9b66a1f..b4f9529a80a0 100644 --- a/src/dashd.cpp +++ b/src/dashd.cpp @@ -56,7 +56,7 @@ static bool AppInit(int argc, char* argv[]) SetupServerArgs(); std::string error; if (!gArgs.ParseParameters(argc, argv, error)) { - return InitError(strprintf("Error parsing command line arguments: %s\n", error)); + return InitError(Untranslated(strprintf("Error parsing command line arguments: %s\n", error))); } if (gArgs.IsArgSet("-printcrashinfo")) { @@ -87,10 +87,10 @@ static bool AppInit(int argc, char* argv[]) bool datadirFromCmdLine = gArgs.IsArgSet("-datadir"); if (datadirFromCmdLine && !fs::is_directory(GetDataDir(false))) { - return InitError(strprintf("Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", ""))); + return InitError(Untranslated(strprintf("Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "")))); } if (!gArgs.ReadConfigFiles(error, true)) { - return InitError(strprintf("Error reading configuration file: %s\n", error)); + return InitError(Untranslated(strprintf("Error reading configuration file: %s\n", error))); } if (!datadirFromCmdLine && !fs::is_directory(GetDataDir(false))) { @@ -101,13 +101,13 @@ static bool AppInit(int argc, char* argv[]) try { SelectParams(gArgs.GetChainName()); } catch (const std::exception& e) { - return InitError(strprintf("%s\n", e.what())); + return InitError(Untranslated(strprintf("%s\n", e.what()))); } // Error out when loose non-argument tokens are encountered on command line for (int i = 1; i < argc; i++) { if (!IsSwitchChar(argv[i][0])) { - return InitError(strprintf("Command line contains unexpected token '%s', see dashd -h for a list of options.\n", argv[i])); + return InitError(Untranslated(strprintf("Command line contains unexpected token '%s', see dashd -h for a list of options.\n", argv[i]))); } } @@ -142,13 +142,13 @@ static bool AppInit(int argc, char* argv[]) // Daemonize if (daemon(1, 0)) { // don't chdir (1), do close FDs (0) - return InitError(strprintf("daemon() failed: %s\n", strerror(errno))); + return InitError(Untranslated(strprintf("daemon() failed: %s\n", strerror(errno)))); } #if defined(MAC_OSX) #pragma GCC diagnostic pop #endif #else - return InitError("-daemon is not supported on this operating system\n"); + return InitError(Untranslated("-daemon is not supported on this operating system\n")); #endif // HAVE_DECL_DAEMON } // Lock data directory after daemonization diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 551077f7d848..ba0d26eac448 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -219,7 +219,7 @@ static bool InitRPCAuthentication() LogPrintf("Using random cookie authentication.\n"); if (!GenerateAuthCookie(&strRPCUserColonPass)) { uiInterface.ThreadSafeMessageBox( - _("Error: A fatal internal error occurred, see debug.log for details").translated, // Same message as AbortNode + _("Error: A fatal internal error occurred, see debug.log for details"), // Same message as AbortNode "", CClientUIInterface::MSG_ERROR); return false; } diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 1c63c33fd59e..610ab29524ff 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -5,14 +5,15 @@ #include #include -#include -#include -#include #include #include // For HTTP status codes #include #include #include +#include +#include +#include +#include #include #include @@ -173,7 +174,7 @@ static bool InitHTTPAllowList() 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 index 970cc8798c73..8ff841082bce 100644 --- a/src/index/base.cpp +++ b/src/index/base.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -22,7 +23,7 @@ static void FatalError(const char* fmt, const Args&... args) SetMiscWarning(strMessage); LogPrintf("*** %s\n", strMessage); uiInterface.ThreadSafeMessageBox( - "Error: A fatal internal error occurred, see debug.log for details", + 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 index 3559e51a8f96..8127286c5dd4 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -151,7 +151,7 @@ static fs::path GetPidFile() tfm::format(file, "%d\n", getpid()); return true; } else { - return InitError(strprintf(_("Unable to create the PID file '%s': %s").translated, GetPidFile().string(), std::strerror(errno))); + return InitError(strprintf(_("Unable to create the PID file '%s': %s"), GetPidFile().string(), std::strerror(errno))); } } #endif @@ -1031,9 +1031,8 @@ void PeriodicStats() */ static bool InitSanityCheck() { - if(!ECC_InitSanityCheck()) { - InitError("Elliptic curve cryptography sanity check failure. Aborting."); - return false; + if (!ECC_InitSanityCheck()) { + return InitError(Untranslated("Elliptic curve cryptography sanity check failure. Aborting.")); } if (!glibc_sanity_test() || !glibcxx_sanity_test()) @@ -1044,8 +1043,7 @@ static bool InitSanityCheck() } if (!Random_SanityCheck()) { - InitError("OS cryptographic RNG sanity check failure. Aborting."); - return false; + return InitError(Untranslated("OS cryptographic RNG sanity check failure. Aborting.")); } return true; @@ -1230,8 +1228,9 @@ bool AppInitBasicSetup() HeapSetInformation(nullptr, HeapEnableTerminationOnCorruption, nullptr, 0); #endif - if (!SetupNetworking()) - return InitError("Initializing networking failed"); + if (!SetupNetworking()) { + return InitError(Untranslated("Initializing networking failed.")); + } #ifndef WIN32 if (!gArgs.GetBoolArg("-sysperms", false)) { @@ -1268,7 +1267,7 @@ bool AppInitParameterInteraction() // on the command line or in this network's section of the config file. std::string network = gArgs.GetChainName(); for (const auto& arg : gArgs.GetUnsuitableSectionOnlyArgs()) { - return InitError(strprintf(_("Config setting for %s only applied on %s network when in [%s] section.").translated, arg, network, network)); + return InitError(strprintf(_("Config setting for %s only applied on %s network when in [%s] section."), arg, network, network)); } // Warn if unrecognized section name are present in the config file. @@ -1277,7 +1276,7 @@ bool AppInitParameterInteraction() } if (!fs::is_directory(GetBlocksDir())) { - return InitError(strprintf(_("Specified blocks directory \"%s\" does not exist.").translated, gArgs.GetArg("-blocksdir", ""))); + return InitError(strprintf(_("Specified blocks directory \"%s\" does not exist."), gArgs.GetArg("-blocksdir", ""))); } // parse and validate enabled filter types @@ -1289,7 +1288,7 @@ bool AppInitParameterInteraction() for (const auto& name : names) { BlockFilterType filter_type; if (!BlockFilterTypeByName(name, filter_type)) { - return InitError(strprintf(_("Unknown -blockfilterindex value %s.").translated, name)); + return InitError(strprintf(_("Unknown -blockfilterindex value %s."), name)); } g_enabled_filter_types.insert(filter_type); } @@ -1298,7 +1297,7 @@ bool AppInitParameterInteraction() // Signal NODE_COMPACT_FILTERS if peerblockfilters and basic filters index are both enabled. if (gArgs.GetBoolArg("-peerblockfilters", DEFAULT_PEERBLOCKFILTERS)) { if (g_enabled_filter_types.count(BlockFilterType::BASIC_FILTER) != 1) { - return InitError(_("Cannot set -peerblockfilters without -blockfilterindex.").translated); + return InitError(_("Cannot set -peerblockfilters without -blockfilterindex.")); } nLocalServices = ServiceFlags(nLocalServices | NODE_COMPACT_FILTERS); @@ -1307,25 +1306,25 @@ bool AppInitParameterInteraction() // if using block pruning, then disallow txindex and require disabling governance validation if (gArgs.GetArg("-prune", 0)) { if (gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX)) - return InitError(_("Prune mode is incompatible with -txindex.").translated); + return InitError(_("Prune mode is incompatible with -txindex.")); if (!gArgs.GetBoolArg("-disablegovernance", false)) { - return InitError(_("Prune mode is incompatible with -disablegovernance=false.").translated); + return InitError(_("Prune mode is incompatible with -disablegovernance=false.")); } if (!g_enabled_filter_types.empty()) { - return InitError(_("Prune mode is incompatible with -blockfilterindex.").translated); + return InitError(_("Prune mode is incompatible with -blockfilterindex.")); } } if (gArgs.IsArgSet("-devnet")) { // Require setting of ports when running devnet if (gArgs.GetArg("-listen", DEFAULT_LISTEN) && !gArgs.IsArgSet("-port")) { - return InitError(_("-port must be specified when -devnet and -listen are specified").translated); + return InitError(_("-port must be specified when -devnet and -listen are specified")); } if (gArgs.GetArg("-server", false) && !gArgs.IsArgSet("-rpcport")) { - return InitError(_("-rpcport must be specified when -devnet and -server are specified").translated); + return InitError(_("-rpcport must be specified when -devnet and -server are specified")); } if (gArgs.GetArgs("-devnet").size() > 1) { - return InitError(_("-devnet can only be specified once").translated); + return InitError(_("-devnet can only be specified once")); } } @@ -1334,7 +1333,7 @@ bool AppInitParameterInteraction() // -bind and -whitebind can't be set when not listening size_t nUserBind = gArgs.GetArgs("-bind").size() + gArgs.GetArgs("-whitebind").size(); if (nUserBind != 0 && !gArgs.GetBoolArg("-listen", DEFAULT_LISTEN)) { - return InitError("Cannot set -bind or -whitebind together with -listen=0"); + return InitError(Untranslated("Cannot set -bind or -whitebind together with -listen=0")); } // Make sure enough file descriptors are available @@ -1352,7 +1351,7 @@ bool AppInitParameterInteraction() #endif nMaxConnections = std::max(std::min(nMaxConnections, fd_max - nBind - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS), 0); if (nFD < MIN_CORE_FILEDESCRIPTORS) - return InitError(_("Not enough file descriptors available.").translated); + return InitError(_("Not enough file descriptors available.")); nMaxConnections = std::min(nFD - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS, nMaxConnections); if (nMaxConnections < nUserMaxConnections) @@ -1397,7 +1396,7 @@ bool AppInitParameterInteraction() if (gArgs.IsArgSet("-minimumchainwork")) { const std::string minChainWorkStr = gArgs.GetArg("-minimumchainwork", ""); if (!IsHexNumber(minChainWorkStr)) { - return InitError(strprintf("Invalid non-hex (%s) minimum chain work value specified", minChainWorkStr)); + return InitError(strprintf(Untranslated("Invalid non-hex (%s) minimum chain work value specified"), minChainWorkStr)); } nMinimumChainWork = UintToArith256(uint256S(minChainWorkStr)); } else { @@ -1412,21 +1411,21 @@ bool AppInitParameterInteraction() int64_t nMempoolSizeMax = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; int64_t nMempoolSizeMin = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) * 1000 * 40; if (nMempoolSizeMax < 0 || nMempoolSizeMax < nMempoolSizeMin) - return InitError(strprintf(_("-maxmempool must be at least %d MB").translated, std::ceil(nMempoolSizeMin / 1000000.0))); + return InitError(strprintf(_("-maxmempool must be at least %d MB"), std::ceil(nMempoolSizeMin / 1000000.0))); // incremental relay fee sets the minimum feerate increase necessary for BIP 125 replacement in the mempool // and the amount the mempool min fee increases above the feerate of txs evicted due to mempool limiting. if (gArgs.IsArgSet("-incrementalrelayfee")) { CAmount n = 0; if (!ParseMoney(gArgs.GetArg("-incrementalrelayfee", ""), n)) - return InitError(AmountErrMsg("incrementalrelayfee", gArgs.GetArg("-incrementalrelayfee", ""))); + return InitError(Untranslated(AmountErrMsg("incrementalrelayfee", gArgs.GetArg("-incrementalrelayfee", "")))); incrementalRelayFee = CFeeRate(n); } // block pruning; get the amount of disk space (in MiB) to allot for block & undo files int64_t nPruneArg = gArgs.GetArg("-prune", 0); if (nPruneArg < 0) { - return InitError(_("Prune cannot be configured with a negative value.").translated); + return InitError(_("Prune cannot be configured with a negative value.")); } nPruneTarget = (uint64_t) nPruneArg * 1024 * 1024; if (nPruneArg == 1) { // manual pruning: -prune=1 @@ -1437,11 +1436,11 @@ bool AppInitParameterInteraction() if (gArgs.GetBoolArg("-regtest", false)) { // we use 1MB blocks to test this on regtest if (nPruneTarget < 550 * 1024 * 1024) { - return InitError(strprintf(_("Prune configured below the minimum of %d MiB. Please use a higher number.").translated, 550)); + return InitError(strprintf(_("Prune configured below the minimum of %d MiB. Please use a higher number."), 550)); } } else { if (nPruneTarget < MIN_DISK_SPACE_FOR_BLOCK_FILES) { - return InitError(strprintf(_("Prune configured below the minimum of %d MiB. Please use a higher number.").translated, MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024)); + return InitError(strprintf(_("Prune configured below the minimum of %d MiB. Please use a higher number."), MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024)); } } LogPrintf("Prune configured to target %u MiB on disk for block and undo files.\n", nPruneTarget / 1024 / 1024); @@ -1455,13 +1454,13 @@ bool AppInitParameterInteraction() peer_connect_timeout = gArgs.GetArg("-peertimeout", DEFAULT_PEER_CONNECT_TIMEOUT); if (peer_connect_timeout <= 0) { - return InitError("peertimeout cannot be configured with a negative value."); + return InitError(Untranslated("peertimeout cannot be configured with a negative value.")); } if (gArgs.IsArgSet("-minrelaytxfee")) { CAmount n = 0; if (!ParseMoney(gArgs.GetArg("-minrelaytxfee", ""), n)) { - return InitError(AmountErrMsg("minrelaytxfee", gArgs.GetArg("-minrelaytxfee", ""))); + return InitError(Untranslated(AmountErrMsg("minrelaytxfee", gArgs.GetArg("-minrelaytxfee", "")))); } // High fee check is done afterward in CWallet::CreateWalletFromFile() ::minRelayTxFee = CFeeRate(n); @@ -1477,7 +1476,7 @@ bool AppInitParameterInteraction() { CAmount n = 0; if (!ParseMoney(gArgs.GetArg("-blockmintxfee", ""), n)) - return InitError(AmountErrMsg("blockmintxfee", gArgs.GetArg("-blockmintxfee", ""))); + return InitError(Untranslated(AmountErrMsg("blockmintxfee", gArgs.GetArg("-blockmintxfee", "")))); } // Feerate used to define dust. Shouldn't be changed lightly as old @@ -1486,13 +1485,13 @@ bool AppInitParameterInteraction() { CAmount n = 0; if (!ParseMoney(gArgs.GetArg("-dustrelayfee", ""), n)) - return InitError(AmountErrMsg("dustrelayfee", gArgs.GetArg("-dustrelayfee", ""))); + return InitError(Untranslated(AmountErrMsg("dustrelayfee", gArgs.GetArg("-dustrelayfee", "")))); dustRelayFee = CFeeRate(n); } fRequireStandard = !gArgs.GetBoolArg("-acceptnonstdtxn", !chainparams.RequireStandard()); if (!chainparams.IsTestChain() && !fRequireStandard) { - return InitError(strprintf("acceptnonstdtxn is not currently supported for %s chain", chainparams.NetworkIDString())); + return InitError(strprintf(Untranslated("acceptnonstdtxn is not currently supported for %s chain"), chainparams.NetworkIDString())); } nBytesPerSigOp = gArgs.GetArg("-bytespersigop", nBytesPerSigOp); @@ -1517,7 +1516,7 @@ bool AppInitParameterInteraction() InitWarning("-llmq-qvvec-sync set but recovery is disabled due to -llmq-data-recovery=0"); } } catch (const std::invalid_argument& e) { - return InitError(e.what()); + return InitError(Untranslated(e.what())); } if (gArgs.IsArgSet("-maxorphantx")) { @@ -1530,22 +1529,22 @@ bool AppInitParameterInteraction() if (gArgs.IsArgSet("-masternodeblsprivkey")) { if (!gArgs.GetBoolArg("-listen", DEFAULT_LISTEN) && Params().RequireRoutableExternalIP()) { - return InitError("Masternode must accept connections from outside, set -listen=1"); + return InitError(Untranslated("Masternode must accept connections from outside, set -listen=1")); } if (!gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX)) { - return InitError("Masternode must have transaction index enabled, set -txindex=1"); + return InitError(Untranslated("Masternode must have transaction index enabled, set -txindex=1")); } if (!gArgs.GetBoolArg("-peerbloomfilters", DEFAULT_PEERBLOOMFILTERS)) { - return InitError("Masternode must have bloom filters enabled, set -peerbloomfilters=1"); + return InitError(Untranslated("Masternode must have bloom filters enabled, set -peerbloomfilters=1")); } if (gArgs.GetArg("-prune", 0) > 0) { - return InitError("Masternode must have no pruning enabled, set -prune=0"); + return InitError(Untranslated("Masternode must have no pruning enabled, set -prune=0")); } if (gArgs.GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS) < DEFAULT_MAX_PEER_CONNECTIONS) { - return InitError(strprintf("Masternode must be able to handle at least %d connections, set -maxconnections=%d", DEFAULT_MAX_PEER_CONNECTIONS, DEFAULT_MAX_PEER_CONNECTIONS)); + return InitError(strprintf(Untranslated("Masternode must be able to handle at least %d connections, set -maxconnections=%d"), DEFAULT_MAX_PEER_CONNECTIONS, DEFAULT_MAX_PEER_CONNECTIONS)); } if (gArgs.GetBoolArg("-disablegovernance", false)) { - return InitError(_("You can not disable governance validation on a masternode.").translated); + return InitError(_("You can not disable governance validation on a masternode.")); } } @@ -1569,10 +1568,10 @@ static bool LockDataDirectory(bool probeOnly) // Make sure only a single Dash Core process is using the data directory. fs::path datadir = GetDataDir(); if (!DirIsWritable(datadir)) { - return InitError(strprintf(_("Cannot write to data directory '%s'; check permissions.").translated, datadir.string())); + return InitError(strprintf(_("Cannot write to data directory '%s'; check permissions."), datadir.string())); } if (!LockDirectory(datadir, ".lock", probeOnly)) { - return InitError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running.").translated, datadir.string(), PACKAGE_NAME)); + return InitError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running."), datadir.string(), PACKAGE_NAME)); } return true; } @@ -1590,7 +1589,7 @@ bool AppInitSanityChecks() // Sanity check if (!InitSanityCheck()) - return InitError(strprintf(_("Initialization sanity check failed. %s is shutting down.").translated, PACKAGE_NAME)); + return InitError(strprintf(_("Initialization sanity check failed. %s is shutting down."), PACKAGE_NAME)); // Probe the data directory lock to give an early error message, if possible // We cannot hold the data directory lock here, as the forking for daemon() hasn't yet happened, @@ -1628,7 +1627,7 @@ bool AppInitMain(InitInterfaces& interfaces) } } if (!LogInstance().StartLogging()) { - return InitError(strprintf("Could not open debug log file %s", + return InitError(strprintf(Untranslated("Could not open debug log file %s"), LogInstance().m_file_path.string())); } @@ -1690,19 +1689,19 @@ bool AppInitMain(InitInterfaces& interfaces) } for (const auto& address: vSporkAddresses) { if (!sporkManager.SetSporkAddress(address)) { - return InitError(_("Invalid spork address specified with -sporkaddr").translated); + return InitError(_("Invalid spork address specified with -sporkaddr")); } } int minsporkkeys = gArgs.GetArg("-minsporkkeys", Params().MinSporkKeys()); if (!sporkManager.SetMinSporkKeys(minsporkkeys)) { - return InitError(_("Invalid minimum number of spork signers specified with -minsporkkeys").translated); + return InitError(_("Invalid minimum number of spork signers specified with -minsporkkeys")); } if (gArgs.IsArgSet("-sporkkey")) { // spork priv key if (!sporkManager.SetPrivKey(gArgs.GetArg("-sporkkey", ""))) { - return InitError(_("Unable to sign spork message, wrong key?").translated); + return InitError(_("Unable to sign spork message, wrong key?")); } } @@ -1742,7 +1741,7 @@ bool AppInitMain(InitInterfaces& interfaces) { uiInterface.InitMessage_connect(SetRPCWarmupStatus); if (!AppInitServers()) - return InitError(_("Unable to start HTTP server. See debug log for details.").translated); + return InitError(_("Unable to start HTTP server. See debug log for details.")); } // ********************************************************* Step 5: verify wallet database integrity @@ -1778,12 +1777,12 @@ bool AppInitMain(InitInterfaces& interfaces) for (const std::string& cmt : gArgs.GetArgs("-uacomment")) { if (cmt != SanitizeString(cmt, SAFE_CHARS_UA_COMMENT)) - return InitError(strprintf(_("User Agent comment (%s) contains unsafe characters.").translated, cmt)); + return InitError(strprintf(_("User Agent comment (%s) contains unsafe characters."), cmt)); uacomments.push_back(cmt); } strSubVersion = FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, uacomments); if (strSubVersion.size() > MAX_SUBVERSION_LENGTH) { - return InitError(strprintf(_("Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.").translated, + return InitError(strprintf(_("Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments."), strSubVersion.size(), MAX_SUBVERSION_LENGTH)); } @@ -1792,7 +1791,7 @@ bool AppInitMain(InitInterfaces& interfaces) for (const std::string& snet : gArgs.GetArgs("-onlynet")) { enum Network net = ParseNetwork(snet); if (net == NET_UNROUTABLE) - return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'").translated, snet)); + return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet)); nets.insert(net); } for (int n = 0; n < NET_MAX; n++) { @@ -1813,12 +1812,12 @@ bool AppInitMain(InitInterfaces& interfaces) if (proxyArg != "" && proxyArg != "0") { CService proxyAddr; if (!Lookup(proxyArg.c_str(), proxyAddr, 9050, fNameLookup)) { - return InitError(strprintf(_("Invalid -proxy address or hostname: '%s'").translated, proxyArg)); + return InitError(strprintf(_("Invalid -proxy address or hostname: '%s'"), proxyArg)); } proxyType addrProxy = proxyType(proxyAddr, proxyRandomize); if (!addrProxy.IsValid()) - return InitError(strprintf(_("Invalid -proxy address or hostname: '%s'").translated, proxyArg)); + return InitError(strprintf(_("Invalid -proxy address or hostname: '%s'"), proxyArg)); SetProxy(NET_IPV4, addrProxy); SetProxy(NET_IPV6, addrProxy); @@ -1837,11 +1836,11 @@ bool AppInitMain(InitInterfaces& interfaces) } else { CService onionProxy; if (!Lookup(onionArg.c_str(), onionProxy, 9050, fNameLookup)) { - return InitError(strprintf(_("Invalid -onion address or hostname: '%s'").translated, onionArg)); + return InitError(strprintf(_("Invalid -onion address or hostname: '%s'"), onionArg)); } proxyType addrOnion = proxyType(onionProxy, proxyRandomize); if (!addrOnion.IsValid()) - return InitError(strprintf(_("Invalid -onion address or hostname: '%s'").translated, onionArg)); + return InitError(strprintf(_("Invalid -onion address or hostname: '%s'"), onionArg)); SetProxy(NET_ONION, addrOnion); SetReachable(NET_ONION, true); } @@ -1857,7 +1856,7 @@ bool AppInitMain(InitInterfaces& interfaces) if (Lookup(strAddr.c_str(), addrLocal, GetListenPort(), fNameLookup) && addrLocal.IsValid()) AddLocal(addrLocal, LOCAL_MANUAL); else - return InitError(ResolveErrMsg("externalip", strAddr)); + return InitError(Untranslated(ResolveErrMsg("externalip", strAddr))); } // Read asmap file if configured @@ -1870,12 +1869,12 @@ bool AppInitMain(InitInterfaces& interfaces) asmap_path = GetDataDir() / asmap_path; } if (!fs::exists(asmap_path)) { - InitError(strprintf(_("Could not find asmap file %s").translated, asmap_path)); + InitError(strprintf(_("Could not find asmap file %s"), asmap_path)); return false; } std::vector asmap = CAddrMan::DecodeAsmap(asmap_path); if (asmap.size() == 0) { - InitError(strprintf(_("Could not parse asmap file %s").translated, asmap_path)); + InitError(strprintf(_("Could not parse asmap file %s"), asmap_path)); return false; } const uint256 asmap_version = SerializeHash(asmap); @@ -1908,7 +1907,7 @@ bool AppInitMain(InitInterfaces& interfaces) uiInterface.InitMessage(_("Loading sporks cache...").translated); CFlatDB flatdb6("sporks.dat", "magicSporkCache"); if (!flatdb6.Load(sporkManager)) { - return InitError(_("Failed to load sporks cache from").translated + "\n" + (GetDataDir() / "sporks.dat").string()); + return InitError(strprintf(_("Failed to load sporks cache from %s"), (GetDataDir() / "sporks.dat").string())); } // ********************************************************* Step 7b: load block chain @@ -1953,7 +1952,7 @@ bool AppInitMain(InitInterfaces& interfaces) while (!fLoaded && !ShutdownRequested()) { bool fReset = fReindex; - std::string strLoadError; + bilingual_str strLoadError; uiInterface.InitMessage(_("Loading block index...").translated); @@ -1994,47 +1993,47 @@ bool AppInitMain(InitInterfaces& interfaces) // From here on out fReindex and fReset mean something different! if (!LoadBlockIndex(chainparams)) { if (ShutdownRequested()) break; - strLoadError = _("Error loading block database").translated; + strLoadError = _("Error loading block database"); break; } if (!fDisableGovernance && !gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX) && chainparams.NetworkIDString() != CBaseChainParams::REGTEST) { // TODO remove this when pruning is fixed. See https://github.com/dashpay/dash/pull/1817 and https://github.com/dashpay/dash/pull/1743 - return InitError(_("Transaction index can't be disabled with governance validation enabled. Either start with -disablegovernance command line switch or enable transaction index.").translated); + return InitError(_("Transaction index can't be disabled with governance validation enabled. Either start with -disablegovernance command line switch or enable transaction index.")); } // If the loaded chain has a wrong genesis, bail out immediately // (we're likely using a testnet datadir, or the other way around). if (!::BlockIndex().empty() && !LookupBlockIndex(chainparams.GetConsensus().hashGenesisBlock)) { - return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?").translated); + return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?")); } if (!chainparams.GetConsensus().hashDevnetGenesisBlock.IsNull() && !::BlockIndex().empty() && ::BlockIndex().count(chainparams.GetConsensus().hashDevnetGenesisBlock) == 0) - return InitError(_("Incorrect or no devnet genesis block found. Wrong datadir for devnet specified?").translated); + return InitError(_("Incorrect or no devnet genesis block found. Wrong datadir for devnet specified?")); // Check for changed -addressindex state if (fAddressIndex != gArgs.GetBoolArg("-addressindex", DEFAULT_ADDRESSINDEX)) { - strLoadError = _("You need to rebuild the database using -reindex to change -addressindex").translated; + strLoadError = _("You need to rebuild the database using -reindex to change -addressindex"); break; } // Check for changed -timestampindex state if (fTimestampIndex != gArgs.GetBoolArg("-timestampindex", DEFAULT_TIMESTAMPINDEX)) { - strLoadError = _("You need to rebuild the database using -reindex to change -timestampindex").translated; + strLoadError = _("You need to rebuild the database using -reindex to change -timestampindex"); break; } // Check for changed -spentindex state if (fSpentIndex != gArgs.GetBoolArg("-spentindex", DEFAULT_SPENTINDEX)) { - strLoadError = _("You need to rebuild the database using -reindex to change -spentindex").translated; + strLoadError = _("You need to rebuild the database using -reindex to change -spentindex"); break; } // Check for changed -prune state. What we are concerned about is a user who has pruned blocks // in the past, but is now trying to run unpruned. if (fHavePruned && !fPruneMode) { - strLoadError = _("You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain").translated; + strLoadError = _("You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain"); break; } @@ -2043,7 +2042,7 @@ bool AppInitMain(InitInterfaces& interfaces) // (otherwise we use the one already on disk). // 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; } @@ -2057,20 +2056,20 @@ bool AppInitMain(InitInterfaces& interfaces) ::ChainstateActive().CoinsErrorCatcher().AddReadErrCallback([]() { uiInterface.ThreadSafeMessageBox( - _("Error reading from database, shutting down.").translated, + _("Error reading from database, shutting down."), "", CClientUIInterface::MSG_ERROR); }); // If necessary, upgrade from older database format. // 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; } // ReplayBlocks is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate if (!::ChainstateActive().ReplayBlocks(chainparams)) { - strLoadError = _("Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.").translated; + strLoadError = _("Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate."); break; } @@ -2080,7 +2079,7 @@ bool AppInitMain(InitInterfaces& interfaces) // flush evodb if (!evoDb->CommitRootTransaction()) { - strLoadError = _("Failed to commit EvoDB").translated; + strLoadError = _("Failed to commit EvoDB"); break; } @@ -2089,7 +2088,7 @@ bool AppInitMain(InitInterfaces& interfaces) if (!is_coinsview_empty) { // 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() != NULL); @@ -2097,12 +2096,12 @@ bool AppInitMain(InitInterfaces& interfaces) if (is_coinsview_empty && !evoDb->IsEmpty()) { // EvoDB processed some blocks earlier but we have no blocks anymore, something is wrong - strLoadError = _("Error initializing block database").translated; + strLoadError = _("Error initializing block database"); break; } if (!deterministicMNManager->UpgradeDBIfNeeded() || !llmq::quorumBlockProcessor->UpgradeDB()) { - strLoadError = _("Error upgrading evo database").translated; + strLoadError = _("Error upgrading evo database"); break; } @@ -2118,13 +2117,13 @@ bool AppInitMain(InitInterfaces& interfaces) if (tip && tip->nTime > GetAdjustedTime() + 2 * 60 * 60) { strLoadError = _("The block database contains a block which appears to be from the future. " "This may be due 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; + "Only rebuild the block database if you are sure that your computer's date and time are correct"); break; } if (!CVerifyDB().VerifyDB(chainparams, &::ChainstateActive().CoinsDB(), gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL), gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS))) { - strLoadError = _("Corrupted block database detected").translated; + strLoadError = _("Corrupted block database detected"); break; } @@ -2134,7 +2133,7 @@ bool AppInitMain(InitInterfaces& interfaces) } } catch (const std::exception& e) { LogPrintf("%s\n", e.what()); - strLoadError = _("Error opening block database").translated; + strLoadError = _("Error opening block database"); break; } @@ -2146,8 +2145,8 @@ bool AppInitMain(InitInterfaces& interfaces) // 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); if (fRet) { fReindex = true; @@ -2231,7 +2230,7 @@ bool AppInitMain(InitInterfaces& interfaces) auto binKey = ParseHex(strMasterNodeBLSPrivKey); CBLSSecretKey keyOperator(binKey); if (!keyOperator.IsValid()) { - return InitError(_("Invalid masternodeblsprivkey. Please see documentation.").translated); + return InitError(_("Invalid masternodeblsprivkey. Please see documentation.")); } fMasternodeMode = true; { @@ -2284,12 +2283,12 @@ bool AppInitMain(InitInterfaces& interfaces) CFlatDB flatdb1(strDBName, "magicMasternodeCache"); if (fLoadCacheFiles) { if(!flatdb1.Load(mmetaman)) { - return InitError(_("Failed to load masternode cache from").translated + "\n" + (pathDB / strDBName).string()); + return InitError(strprintf(_("Failed to load masternode cache from %s"), (pathDB / strDBName).string())); } } else { CMasternodeMetaMan mmetamanTmp; if(!flatdb1.Dump(mmetamanTmp)) { - return InitError(_("Failed to clear masternode cache at").translated + "\n" + (pathDB / strDBName).string()); + return InitError(strprintf(_("Failed to clear masternode cache at %s"), (pathDB / strDBName).string())); } } @@ -2298,13 +2297,13 @@ bool AppInitMain(InitInterfaces& interfaces) CFlatDB flatdb3(strDBName, "magicGovernanceCache"); if (fLoadCacheFiles && !fDisableGovernance) { if(!flatdb3.Load(governance)) { - return InitError(_("Failed to load governance cache from").translated + "\n" + (pathDB / strDBName).string()); + return InitError(strprintf(_("Failed to load governance cache from %s"), (pathDB / strDBName).string())); } governance.InitOnLoad(); } else { CGovernanceManager governanceTmp; if(!flatdb3.Dump(governanceTmp)) { - return InitError(_("Failed to clear governance cache at").translated + "\n" + (pathDB / strDBName).string()); + return InitError(strprintf(_("Failed to clear governance cache at %s"), (pathDB / strDBName).string())); } } @@ -2313,12 +2312,12 @@ bool AppInitMain(InitInterfaces& interfaces) CFlatDB flatdb4(strDBName, "magicFulfilledCache"); if (fLoadCacheFiles) { if(!flatdb4.Load(netfulfilledman)) { - return InitError(_("Failed to load fulfilled requests cache from").translated + "\n" + (pathDB / strDBName).string()); + return InitError(strprintf(_("Failed to load fulfilled requests cache from %s"),(pathDB / strDBName).string())); } } else { CNetFulfilledRequestManager netfulfilledmanTmp; if(!flatdb4.Dump(netfulfilledmanTmp)) { - return InitError(_("Failed to clear fulfilled requests cache at").translated + "\n" + (pathDB / strDBName).string()); + return InitError(strprintf(_("Failed to clear fulfilled requests cache at %s"),(pathDB / strDBName).string())); } } @@ -2347,11 +2346,11 @@ bool AppInitMain(InitInterfaces& interfaces) // ********************************************************* Step 11: import blocks if (!CheckDiskSpace(GetDataDir())) { - InitError(strprintf(_("Error: Disk space is low for %s").translated, GetDataDir())); + InitError(strprintf(_("Error: Disk space is low for %s"), GetDataDir())); return false; } if (!CheckDiskSpace(GetBlocksDir())) { - InitError(strprintf(_("Error: Disk space is low for %s").translated, GetBlocksDir())); + InitError(strprintf(_("Error: Disk space is low for %s"), GetBlocksDir())); return false; } @@ -2433,21 +2432,21 @@ bool AppInitMain(InitInterfaces& interfaces) for (const std::string& strBind : gArgs.GetArgs("-bind")) { CService addrBind; if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false)) { - return InitError(ResolveErrMsg("bind", strBind)); + return InitError(Untranslated(ResolveErrMsg("bind", strBind))); } connOptions.vBinds.push_back(addrBind); } for (const std::string& strBind : gArgs.GetArgs("-whitebind")) { NetWhitebindPermissions whitebind; std::string error; - if (!NetWhitebindPermissions::TryParse(strBind, whitebind, error)) return InitError(error); + if (!NetWhitebindPermissions::TryParse(strBind, whitebind, error)) return InitError(Untranslated(error)); connOptions.vWhiteBinds.push_back(whitebind); } for (const auto& net : gArgs.GetArgs("-whitelist")) { NetWhitelistPermissions subnet; std::string error; - if (!NetWhitelistPermissions::TryParse(net, subnet, error)) return InitError(error); + if (!NetWhitelistPermissions::TryParse(net, subnet, error)) return InitError(Untranslated(error)); connOptions.vWhitelistedRange.push_back(subnet); } @@ -2478,7 +2477,7 @@ bool AppInitMain(InitInterfaces& interfaces) connOptions.socketEventsMode = CConnman::SOCKETEVENTS_KQUEUE; #endif } else { - return InitError(strprintf(_("Invalid -socketevents ('%s') specified. Only these modes are supported: %s").translated, strSocketEventsMode, GetSupportedSocketEventsStr())); + return InitError(strprintf(_("Invalid -socketevents ('%s') specified. Only these modes are supported: %s"), strSocketEventsMode, GetSupportedSocketEventsStr())); } if (!g_connman->Start(scheduler, connOptions)) { diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index 09bfc08016c9..a20584e2d117 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -345,7 +345,7 @@ class ChainImpl : public Chain int64_t getAdjustedTime() override { return GetAdjustedTime(); } void initMessage(const std::string& message) override { ::uiInterface.InitMessage(message); } void initWarning(const std::string& message) override { InitWarning(message); } - void initError(const std::string& message) override { InitError(message); } + void initError(const bilingual_str& message) override { InitError(message); } void loadWallet(std::unique_ptr wallet) override { ::uiInterface.LoadWallet(wallet); } void showProgress(const std::string& title, int progress, bool resume_possible) override { diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index a0a54124ead6..946c69ff8626 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -23,6 +23,7 @@ class CFeeRate; class CBlockIndex; class Coin; class uint256; +struct bilingual_str; struct CBlockLocator; struct FeeCalculation; enum class MemPoolRemovalReason; @@ -216,7 +217,7 @@ class Chain virtual void initWarning(const std::string& message) = 0; //! Send init error. - virtual void initError(const std::string& message) = 0; + virtual void initError(const bilingual_str& message) = 0; //! Send wallet load notification to the GUI. virtual void loadWallet(std::unique_ptr wallet) = 0; diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp index c7b3ad96df3f..e818f3fb66c3 100644 --- a/src/interfaces/node.cpp +++ b/src/interfaces/node.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -177,7 +178,7 @@ class NodeImpl : public Node MasternodeSyncImpl m_masternodeSync; CoinJoinOptionsImpl m_coinjoin; - void initError(const std::string& message) override { InitError(message); } + void initError(const std::string& message) override { InitError(Untranslated(message)); } bool parseParameters(int argc, const char* const argv[], std::string& error) override { return gArgs.ParseParameters(argc, argv, error); diff --git a/src/interfaces/node.h b/src/interfaces/node.h index 5658a0274903..1cb96f358e87 100644 --- a/src/interfaces/node.h +++ b/src/interfaces/node.h @@ -294,11 +294,11 @@ class Node //! Register handler for message box messages. using MessageBoxFn = - std::function; + std::function; virtual std::unique_ptr handleMessageBox(MessageBoxFn fn) = 0; //! Register handler for question messages. - using QuestionFn = std::function; diff --git a/src/net.cpp b/src/net.cpp index 33804a8cb909..dd1e55e54d3f 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2612,9 +2612,8 @@ void CConnman::ThreadMessageHandler() -bool CConnman::BindListenPort(const CService& addrBind, std::string& strError, NetPermissionFlags permissions) +bool CConnman::BindListenPort(const CService& addrBind, bilingual_str& strError, NetPermissionFlags permissions) { - strError = ""; int nOne = 1; // Create socket for listening for incoming connections @@ -2622,16 +2621,16 @@ bool CConnman::BindListenPort(const CService& addrBind, std::string& strError, N 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; } @@ -2655,10 +2654,10 @@ bool CConnman::BindListenPort(const CService& addrBind, std::string& strError, N { int nErr = WSAGetLastError(); if (nErr == WSAEADDRINUSE) - strError = strprintf(_("Unable to bind to %s on this computer. %s is probably already running.").translated, addrBind.ToString(), PACKAGE_NAME); + strError = strprintf(_("Unable to bind to %s on this computer. %s is probably already running."), addrBind.ToString(), PACKAGE_NAME); else - strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)").translated, addrBind.ToString(), NetworkErrorString(nErr)); - LogPrintf("%s\n", strError); + strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)"), addrBind.ToString(), NetworkErrorString(nErr)); + LogPrintf("%s\n", strError.original); CloseSocket(hListenSocket); return false; } @@ -2667,8 +2666,8 @@ bool CConnman::BindListenPort(const CService& addrBind, std::string& strError, N // Listen for incoming connections if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR) { - strError = strprintf(_("Error: Listening for incoming connections failed (listen returned error %s)").translated, NetworkErrorString(WSAGetLastError())); - LogPrintf("%s\n", strError); + strError = strprintf(_("Error: Listening for incoming connections failed (listen returned error %s)"), NetworkErrorString(WSAGetLastError())); + LogPrintf("%s\n", strError.original); CloseSocket(hListenSocket); return false; } @@ -2678,8 +2677,8 @@ bool CConnman::BindListenPort(const CService& addrBind, std::string& strError, N struct kevent event; EV_SET(&event, hListenSocket, EVFILT_READ, EV_ADD, 0, 0, nullptr); if (kevent(kqueuefd, &event, 1, nullptr, 0, nullptr) != 0) { - strError = strprintf(_("Error: failed to add socket to kqueuefd (kevent returned error %s)").translated, NetworkErrorString(WSAGetLastError())); - LogPrintf("%s\n", strError); + strError = strprintf(_("Error: failed to add socket to kqueuefd (kevent returned error %s)"), NetworkErrorString(WSAGetLastError())); + LogPrintf("%s\n", strError.original); CloseSocket(hListenSocket); return false; } @@ -2692,8 +2691,8 @@ bool CConnman::BindListenPort(const CService& addrBind, std::string& strError, N event.data.fd = hListenSocket; event.events = EPOLLIN; if (epoll_ctl(epollfd, EPOLL_CTL_ADD, hListenSocket, &event) != 0) { - strError = strprintf(_("Error: failed to add socket to epollfd (epoll_ctl returned error %s)").translated, NetworkErrorString(WSAGetLastError())); - LogPrintf("%s\n", strError); + strError = strprintf(_("Error: failed to add socket to epollfd (epoll_ctl returned error %s)"), NetworkErrorString(WSAGetLastError())); + LogPrintf("%s\n", strError.original); CloseSocket(hListenSocket); return false; } @@ -2795,7 +2794,7 @@ NodeId CConnman::GetNewNodeId() bool CConnman::Bind(const CService &addr, unsigned int flags, NetPermissionFlags permissions) { 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(strError, "", CClientUIInterface::MSG_ERROR); @@ -2862,7 +2861,7 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions) if (fListen && !InitBinds(connOptions.vBinds, connOptions.vWhiteBinds)) { if (clientInterface) { clientInterface->ThreadSafeMessageBox( - _("Failed to listen on any port. Use -listen=0 if you want this.").translated, + _("Failed to listen on any port. Use -listen=0 if you want this."), "", CClientUIInterface::MSG_ERROR); } return false; @@ -2969,7 +2968,7 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions) if (connOptions.m_use_addrman_outgoing && !connOptions.m_specified_outgoing.empty()) { if (clientInterface) { clientInterface->ThreadSafeMessageBox( - _("Cannot provide specific connections and have addrman find outgoing connections at the same.").translated, + _("Cannot provide specific connections and have addrman find outgoing connections at the same."), "", CClientUIInterface::MSG_ERROR); } return false; diff --git a/src/net.h b/src/net.h index 1e95b61ef122..daa5dfa20032 100644 --- a/src/net.h +++ b/src/net.h @@ -22,9 +22,9 @@ #include #include #include +#include #include #include -#include #include #include @@ -48,6 +48,7 @@ class CScheduler; class CNode; class BanMan; +struct bilingual_str; /** Default for -whitelistrelay. */ static const bool DEFAULT_WHITELISTRELAY = true; @@ -483,7 +484,7 @@ friend class CNode; NetPermissionFlags m_permissions; }; - bool BindListenPort(const CService& bindAddr, std::string& strError, NetPermissionFlags permissions); + bool BindListenPort(const CService& bindAddr, bilingual_str& strError, NetPermissionFlags permissions); bool Bind(const CService& addr, unsigned int flags, NetPermissionFlags permissions); bool InitBinds(const std::vector& binds, const std::vector& whiteBinds); void ThreadOpenAddedConnections(); diff --git a/src/noui.cpp b/src/noui.cpp index 2de17585300b..c994bc1d8e78 100644 --- a/src/noui.cpp +++ b/src/noui.cpp @@ -6,8 +6,9 @@ #include +#include #include -#include +#include #include @@ -18,7 +19,7 @@ boost::signals2::connection noui_ThreadSafeMessageBoxConn; boost::signals2::connection noui_ThreadSafeQuestionConn; boost::signals2::connection noui_InitMessageConn; -bool noui_ThreadSafeMessageBox(const std::string& message, const std::string& caption, unsigned int style) +bool noui_ThreadSafeMessageBox(const bilingual_str& message, const std::string& caption, unsigned int style) { bool fSecure = style & CClientUIInterface::SECURE; style &= ~CClientUIInterface::SECURE; @@ -43,15 +44,15 @@ bool noui_ThreadSafeMessageBox(const std::string& message, const std::string& ca } if (!fSecure) { - LogPrintf("%s%s\n", strCaption, message); + LogPrintf("%s%s\n", strCaption, message.original); } - tfm::format(std::cerr, "%s%s\n", strCaption, message); + tfm::format(std::cerr, "%s%s\n", strCaption, message.original); return false; } -bool noui_ThreadSafeQuestion(const std::string& /* ignored interactive message */, const std::string& message, const std::string& caption, unsigned int style) +bool noui_ThreadSafeQuestion(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) @@ -66,13 +67,13 @@ void noui_connect() noui_InitMessageConn = uiInterface.InitMessage_connect(noui_InitMessage); } -bool noui_ThreadSafeMessageBoxRedirect(const std::string& message, const std::string& caption, unsigned int style) +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 std::string& message, const std::string& caption, unsigned int style) +bool noui_ThreadSafeQuestionRedirect(const bilingual_str& /* ignored interactive message */, const std::string& message, const std::string& caption, unsigned int style) { LogPrintf("%s: %s\n", caption, message); return false; diff --git a/src/noui.h b/src/noui.h index 174074e75379..0c48a1c728e4 100644 --- a/src/noui.h +++ b/src/noui.h @@ -7,10 +7,12 @@ #include +struct bilingual_str; + /** Non-GUI handler, which logs and prints messages. */ -bool noui_ThreadSafeMessageBox(const std::string& message, const std::string& caption, unsigned int style); +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 std::string& message, const std::string& caption, unsigned int style); +bool noui_ThreadSafeQuestion(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/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 5f2ee4b32011..671edf833d26 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -1494,7 +1495,7 @@ void BitcoinGUI::setAdditionalDataSyncProgress(double nSyncProgress) progressBar->setToolTip(tooltip); } -void BitcoinGUI::message(const QString& title, QString message, unsigned int style, bool* ret) +void BitcoinGUI::message(const QString& title, QString message, unsigned int style, bool* ret, const QString& detailed_message) { // Default title. On macOS, the window title is ignored (as required by the macOS Guidelines). QString strTitle{PACKAGE_NAME}; @@ -1548,6 +1549,7 @@ void BitcoinGUI::message(const QString& title, QString message, unsigned int sty showNormalIfMinimized(); QMessageBox mBox(static_cast(nMBoxIcon), strTitle, message, buttons, this); mBox.setTextFormat(Qt::PlainText); + mBox.setDetailedText(detailed_message); int r = mBox.exec(); if (ret != nullptr) *ret = r == QMessageBox::Ok; @@ -1925,20 +1927,27 @@ void BitcoinGUI::showModalOverlay() modalOverlay->toggleVisibility(); } -static bool ThreadSafeMessageBox(BitcoinGUI* gui, const std::string& message, const std::string& caption, unsigned int style) +static bool ThreadSafeMessageBox(BitcoinGUI* gui, const bilingual_str& message, const std::string& caption, unsigned int style) { bool modal = (style & CClientUIInterface::MODAL); // The SECURE flag has no effect in the Qt GUI. // bool secure = (style & CClientUIInterface::SECURE); style &= ~CClientUIInterface::SECURE; bool ret = false; + + QString detailed_message; // This is original message, in English, for googling and referencing. + 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(QString, QString::fromStdString(message.translated)), Q_ARG(unsigned int, style), - Q_ARG(bool*, &ret)); + Q_ARG(bool*, &ret), + Q_ARG(QString, detailed_message)); assert(invoked); return ret; } diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index 84252271da40..bcd889751605 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -257,13 +257,14 @@ public Q_SLOTS: void setAdditionalDataSyncProgress(double nSyncProgress); /** Notify the user of an event from the core network or transaction handling code. - @param[in] title the message box / notification title - @param[in] message the displayed text - @param[in] style modality and style definitions (icon and used buttons - buttons only for message boxes) - @see CClientUIInterface::MessageBoxFlags - @param[in] ret pointer to a bool that will be modified to whether Ok was clicked (modal only) + @param[in] title the message box / notification title + @param[in] message the displayed text + @param[in] style modality and style definitions (icon and used buttons - buttons only for message boxes) + @see CClientUIInterface::MessageBoxFlags + @param[in] ret pointer to a bool that will be modified to whether Ok was clicked (modal only) + @param[in] detailed_message the text to be displayed in the details area */ - void message(const QString& title, QString message, unsigned int style, bool* ret = nullptr); + void message(const QString& title, QString message, unsigned int style, bool* ret = nullptr, const QString& detailed_message = QString()); #ifdef ENABLE_WALLET void setCurrentWallet(WalletModel* wallet_model); diff --git a/src/timedata.cpp b/src/timedata.cpp index 095206700cd6..02754f469ad0 100644 --- a/src/timedata.cpp +++ b/src/timedata.cpp @@ -101,8 +101,8 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample) if (!fMatch) { fDone = true; - std::string strMessage = strprintf(_("Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.").translated, PACKAGE_NAME); - SetMiscWarning(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."), PACKAGE_NAME); + SetMiscWarning(strMessage.translated); uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_WARNING); } } diff --git a/src/ui_interface.cpp b/src/ui_interface.cpp index 99a061c45801..10014e672fbd 100644 --- a/src/ui_interface.cpp +++ b/src/ui_interface.cpp @@ -4,6 +4,8 @@ #include +#include + #include #include @@ -48,8 +50,8 @@ ADD_SIGNALS_IMPL_WRAPPER(NotifyMasternodeListChanged); ADD_SIGNALS_IMPL_WRAPPER(NotifyAdditionalDataSyncProgressChanged); ADD_SIGNALS_IMPL_WRAPPER(BannedListChanged); -bool CClientUIInterface::ThreadSafeMessageBox(const std::string& 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 std::string& caption, unsigned int style) { return g_ui_signals.ThreadSafeQuestion(message, non_interactive_message, caption, style); } +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 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); } void CClientUIInterface::InitMessage(const std::string& message) { return g_ui_signals.InitMessage(message); } void CClientUIInterface::NotifyNumConnectionsChanged(int newNumConnections) { return g_ui_signals.NotifyNumConnectionsChanged(newNumConnections); } void CClientUIInterface::NotifyNetworkActiveChanged(bool networkActive) { return g_ui_signals.NotifyNetworkActiveChanged(networkActive); } @@ -63,8 +65,7 @@ void CClientUIInterface::NotifyMasternodeListChanged(const CDeterministicMNList& void CClientUIInterface::NotifyAdditionalDataSyncProgressChanged(double nSyncProgress) { return g_ui_signals.NotifyAdditionalDataSyncProgressChanged(nSyncProgress); } void CClientUIInterface::BannedListChanged() { return g_ui_signals.BannedListChanged(); } - -bool InitError(const std::string& str) +bool InitError(const bilingual_str& str) { uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_ERROR); return false; @@ -72,5 +73,5 @@ bool InitError(const std::string& str) void InitWarning(const std::string& str) { - uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_WARNING); + uiInterface.ThreadSafeMessageBox(Untranslated(str), "", CClientUIInterface::MSG_WARNING); } diff --git a/src/ui_interface.h b/src/ui_interface.h index e0afe235d357..8c26201aa31e 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -11,7 +11,10 @@ #include class CBlockIndex; +struct bilingual_str; + class CDeterministicMNList; + namespace boost { namespace signals2 { class connection; @@ -87,10 +90,10 @@ class CClientUIInterface boost::signals2::connection signal_name##_connect(std::function fn); /** Show message box. */ - ADD_SIGNALS_DECL_WRAPPER(ThreadSafeMessageBox, bool, const std::string& message, const std::string& caption, unsigned int style); + ADD_SIGNALS_DECL_WRAPPER(ThreadSafeMessageBox, bool, const bilingual_str& message, const std::string& caption, unsigned int style); /** If possible, ask the user a question. If not, falls back to ThreadSafeMessageBox(noninteractive_message, caption, style) and returns false. */ - ADD_SIGNALS_DECL_WRAPPER(ThreadSafeQuestion, bool, const std::string& message, const std::string& noninteractive_message, const std::string& caption, unsigned int style); + ADD_SIGNALS_DECL_WRAPPER(ThreadSafeQuestion, bool, const bilingual_str& message, const std::string& noninteractive_message, const std::string& caption, unsigned int style); /** Progress message during initialization. */ ADD_SIGNALS_DECL_WRAPPER(InitMessage, void, const std::string& message); @@ -135,10 +138,11 @@ class CClientUIInterface }; /** Show warning message **/ +// TODO: InitWarning() should take a bilingual_str parameter. void InitWarning(const std::string& str); /** Show error message **/ -bool InitError(const std::string& str); +bool InitError(const bilingual_str& str); extern CClientUIInterface uiInterface; diff --git a/src/util/translation.h b/src/util/translation.h index 01b1f6166f83..b4f8fd9f3813 100644 --- a/src/util/translation.h +++ b/src/util/translation.h @@ -27,11 +27,11 @@ inline bilingual_str operator+(const bilingual_str& lhs, const bilingual_str& rh } /** Mark a bilingual_str as untranslated */ -inline static bilingual_str Untranslated(std::string original) { return {original, original}; } +inline bilingual_str Untranslated(std::string original) { return {original, original}; } /** Unary operator to return the original */ -inline static std::string OpOriginal(const bilingual_str& b) { return b.original; } +inline std::string OpOriginal(const bilingual_str& b) { return b.original; } /** Unary operator to return the translation */ -inline static std::string OpTranslated(const bilingual_str& b) { return b.translated; } +inline std::string OpTranslated(const bilingual_str& b) { return b.translated; } namespace tinyformat { template diff --git a/src/validation.cpp b/src/validation.cpp index 81e0e2e3dc89..f897c6c2033e 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1574,14 +1574,15 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex) } /** Abort with a message */ +// TODO: AbortNode() should take bilingual_str userMessage parameter. static bool AbortNode(const std::string& strMessage, const std::string& userMessage = "", unsigned int prefix = 0) { 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, "", CClientUIInterface::MSG_ERROR | CClientUIInterface::MSG_NOPREFIX); + uiInterface.ThreadSafeMessageBox(_("Error: A fatal internal error occurred, see debug.log for details"), "", CClientUIInterface::MSG_ERROR | CClientUIInterface::MSG_NOPREFIX); } StartShutdown(); return false; diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp index 27b5ca230443..0dcd5d914349 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -102,7 +102,7 @@ bool WalletInit::ParameterInteraction() const return true; } else if (gArgs.IsArgSet("-masternodeblsprivkey")) { - return InitError(_("You can not start a masternode with wallet enabled.").translated); + return InitError(_("You can not start a masternode with wallet enabled.")); } const bool is_multiwallet = gArgs.GetArgs("-wallet").size() > 1; @@ -120,7 +120,7 @@ bool WalletInit::ParameterInteraction() const // -zapwallettxes implies a rescan if (zapwallettxes) { if (is_multiwallet) { - return InitError(strprintf("%s is only allowed with a single wallet file", "-zapwallettxes")); + return InitError(strprintf(Untranslated("%s is only allowed with a single wallet file"), "-zapwallettxes")); } if (gArgs.SoftSetBoolArg("-rescan", true)) { LogPrintf("%s: parameter interaction: -zapwallettxes enabled -> setting -rescan=1\n", __func__); @@ -136,14 +136,14 @@ bool WalletInit::ParameterInteraction() const if (is_multiwallet) { if (gArgs.GetBoolArg("-upgradewallet", false)) { - return InitError(strprintf("%s is only allowed with a single wallet file", "-upgradewallet")); + return InitError(strprintf(_("%s is only allowed with a single wallet file"), "-upgradewallet")); } } if (gArgs.GetBoolArg("-sysperms", false)) - return InitError("-sysperms is not allowed in combination with enabled wallet functionality"); + return InitError(Untranslated("-sysperms is not allowed in combination with enabled wallet functionality")); if (gArgs.GetArg("-prune", 0) && gArgs.GetBoolArg("-rescan", false)) - return InitError(_("Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.").translated); + return InitError(_("Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.")); if (gArgs.IsArgSet("-walletbackupsdir")) { if (!fs::is_directory(gArgs.GetArg("-walletbackupsdir", ""))) { @@ -226,7 +226,7 @@ bool WalletInit::ParameterInteraction() const // end PrivateSend -> CoinJoin migration if (gArgs.GetArg("-coinjoindenomshardcap", DEFAULT_COINJOIN_DENOMS_HARDCAP) < gArgs.GetArg("-coinjoindenomsgoal", DEFAULT_COINJOIN_DENOMS_GOAL)) { - return InitError(strprintf(_("%s can't be lower than %s").translated, "-coinjoindenomshardcap", "-coinjoindenomsgoal")); + return InitError(strprintf(_("%s can't be lower than %s"), "-coinjoindenomshardcap", "-coinjoindenomsgoal")); } return true; diff --git a/src/wallet/load.cpp b/src/wallet/load.cpp index 61fd68e19fae..0c915d2ce153 100644 --- a/src/wallet/load.cpp +++ b/src/wallet/load.cpp @@ -23,14 +23,14 @@ bool VerifyWallets(interfaces::Chain& chain, const std::vector& wal // The canonical path cleans the path, preventing >1 Berkeley environment instances for the same directory fs::path canonical_wallet_dir = fs::canonical(wallet_dir, error); if (error || !fs::exists(wallet_dir)) { - chain.initError(strprintf(_("Specified -walletdir \"%s\" does not exist").translated, wallet_dir.string())); + chain.initError(strprintf(_("Specified -walletdir \"%s\" does not exist"), wallet_dir.string())); return false; } else if (!fs::is_directory(wallet_dir)) { - chain.initError(strprintf(_("Specified -walletdir \"%s\" is not a directory").translated, wallet_dir.string())); + chain.initError(strprintf(_("Specified -walletdir \"%s\" is not a directory"), wallet_dir.string())); return false; // The canonical path transforms relative paths into absolute ones, so we check the non-canonical version } else if (!wallet_dir.is_absolute()) { - chain.initError(strprintf(_("Specified -walletdir \"%s\" is a relative path").translated, wallet_dir.string())); + chain.initError(strprintf(_("Specified -walletdir \"%s\" is a relative path"), wallet_dir.string())); return false; } gArgs.ForceSetArg("-walletdir", canonical_wallet_dir.string()); @@ -47,7 +47,7 @@ bool VerifyWallets(interfaces::Chain& chain, const std::vector& wal WalletLocation location(wallet_file); if (!wallet_paths.insert(location.GetPath()).second) { - chain.initError(strprintf(_("Error loading wallet %s. Duplicate -wallet filename specified.").translated, wallet_file)); + chain.initError(strprintf(_("Error loading wallet %s. Duplicate -wallet filename specified."), wallet_file)); return false; } @@ -56,7 +56,7 @@ bool VerifyWallets(interfaces::Chain& chain, const std::vector& wal bool verify_success = CWallet::Verify(chain, location, error_string, warnings); if (!warnings.empty()) chain.initWarning(Join(warnings, "\n", OpTranslated)); if (!verify_success) { - chain.initError(error_string.translated); + chain.initError(error_string); return false; } } @@ -72,7 +72,7 @@ bool LoadWallets(interfaces::Chain& chain, const std::vector& walle std::shared_ptr pwallet = CWallet::CreateWalletFromFile(chain, WalletLocation(walletFile), error_string, warnings); if (!warnings.empty()) chain.initWarning(Join(warnings, "\n", OpTranslated)); if (!pwallet) { - chain.initError(error_string.translated); + chain.initError(error_string); return false; } } From b0de56db6a0836cb00ea5c4bf90e98d8d288474c Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Wed, 13 May 2020 20:30:31 +0200 Subject: [PATCH 02/11] Merge #18922: gui: Do not translate InitWarning messages in debug.log MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 78be8d97d3d750fcfbbe509a72639b7b30b7bd18 util: Drop OpOriginal() and OpTranslated() (Hennadii Stepanov) da16f95c3fecf4ee1e9a1dc4333b0b92cd981afd gui: Do not translate InitWarning messages in debug.log (Hennadii Stepanov) 4c9b9a4882e68835f16a52f1f0657efe47e589b5 util: Enhance Join() (Hennadii Stepanov) fe05dd0611cfc2929a7fdec04ca5948bccf0233b util: Enhance bilingual_str (Hennadii Stepanov) Pull request description: This PR forces the `bitcoin-qt` to write `InitWarning()` messages to the `debug.log` file in untranslated form, i.e., in English. On master (376294cde6b1588cb17055d8fde567eaf5848c3c): ``` $ ./src/qt/bitcoin-qt -lang=nl -debug=vladidation -printtoconsole | grep 'vladi' Warning: Niet-ondersteunde logcategorie -debug=vladidation. 2020-05-09T12:39:59Z Warning: Niet-ondersteunde logcategorie -debug=vladidation. 2020-05-09T12:40:02Z Command-line arg: debug="vladidation" ``` With this PR: ``` $ ./src/qt/bitcoin-qt -lang=nl -debug=vladidation -printtoconsole | grep 'vladi' Warning: Unsupported logging category -debug=vladidation. 2020-05-09T12:42:04Z Warning: Unsupported logging category -debug=vladidation. 2020-05-09T12:42:35Z Command-line arg: debug="vladidation" ``` ![Screenshot from 2020-05-09 15-42-31](https://user-images.githubusercontent.com/32963518/81474073-c7a50e00-920b-11ea-8775-c41122dacafe.png) Related to #16218. ACKs for top commit: laanwj: ACK 78be8d97d3d750fcfbbe509a72639b7b30b7bd18 jonasschnelli: utACK 78be8d97d3d750fcfbbe509a72639b7b30b7bd18 MarcoFalke: ACK 78be8d97d3d750fcfbbe509a72639b7b30b7bd18 📢 Tree-SHA512: 48e9ecd23c4dd8ec262e3eb94f8e30944bcc9c6c163245fb837b2e0c484d4d0b4f47f7abc638c14edc27d635d340ba3ee4ba4506b062399e9cf59a1564c98755 # Conflicts: # src/wallet/load.cpp --- src/coinjoin/client.cpp | 2 +- src/init.cpp | 20 ++++++++++---------- src/interfaces/chain.cpp | 2 +- src/interfaces/chain.h | 2 +- src/qt/walletcontroller.cpp | 4 ++-- src/qt/walletmodel.cpp | 2 +- src/ui_interface.cpp | 4 ++-- src/ui_interface.h | 3 +-- src/util/translation.h | 18 ++++++++++-------- src/wallet/init.cpp | 22 +++++++++++----------- src/wallet/load.cpp | 4 ++-- src/wallet/rpcwallet.cpp | 4 ++-- src/wallet/wallet.cpp | 10 +++++----- 13 files changed, 49 insertions(+), 48 deletions(-) diff --git a/src/coinjoin/client.cpp b/src/coinjoin/client.cpp index b450f1ea7984..32792be6de63 100644 --- a/src/coinjoin/client.cpp +++ b/src/coinjoin/client.cpp @@ -740,7 +740,7 @@ bool CCoinJoinClientManager::CheckAutomaticBackup() if (!mixingWallet.AutoBackupWallet("", errorString, warnings)) { if (!warnings.empty()) { // There were some issues saving backup but yet more or less safe to continue - LogPrint(BCLog::COINJOIN, "CCoinJoinClientManager::CheckAutomaticBackup -- WARNING! Something went wrong on automatic backup: %s\n", Join(warnings, "\n", OpTranslated)); + LogPrint(BCLog::COINJOIN, "CCoinJoinClientManager::CheckAutomaticBackup -- WARNING! Something went wrong on automatic backup: %s\n", Join(warnings, Untranslated("\n")).translated); } if (!errorString.original.empty()) { // Things are really broken diff --git a/src/init.cpp b/src/init.cpp index 8127286c5dd4..623ed3675980 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1272,7 +1272,7 @@ bool AppInitParameterInteraction() // Warn if unrecognized section name are present in the config file. for (const auto& section : gArgs.GetUnrecognizedSections()) { - InitWarning(strprintf("%s:%i " + _("Section [%s] is not recognized.").translated, section.m_file, section.m_line, section.m_name)); + InitWarning(strprintf(Untranslated("%s:%i ") + _("Section [%s] is not recognized."), section.m_file, section.m_line, section.m_name)); } if (!fs::is_directory(GetBlocksDir())) { @@ -1355,7 +1355,7 @@ bool AppInitParameterInteraction() nMaxConnections = std::min(nFD - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS, nMaxConnections); if (nMaxConnections < nUserMaxConnections) - InitWarning(strprintf(_("Reducing -maxconnections from %d to %d, because of system limitations.").translated, nUserMaxConnections, nMaxConnections)); + InitWarning(strprintf(_("Reducing -maxconnections from %d to %d, because of system limitations."), nUserMaxConnections, nMaxConnections)); // ********************************************************* Step 3: parameter-to-internal-flags if (gArgs.IsArgSet("-debug")) { @@ -1366,7 +1366,7 @@ bool AppInitParameterInteraction() [](std::string cat){return cat == "0" || cat == "none";})) { for (const auto& cat : categories) { if (!LogInstance().EnableCategory(cat)) { - InitWarning(strprintf(_("Unsupported logging category %s=%s.").translated, "-debug", cat)); + InitWarning(strprintf(_("Unsupported logging category %s=%s."), "-debug", cat)); } } } @@ -1375,7 +1375,7 @@ bool AppInitParameterInteraction() // Now remove the logging categories which were explicitly excluded for (const std::string& cat : gArgs.GetArgs("-debugexclude")) { if (!LogInstance().DisableCategory(cat)) { - InitWarning(strprintf(_("Unsupported logging category %s=%s.").translated, "-debugexclude", cat)); + InitWarning(strprintf(_("Unsupported logging category %s=%s."), "-debugexclude", cat)); } } @@ -1513,18 +1513,18 @@ bool AppInitParameterInteraction() const bool fRecoveryEnabled{llmq::CLLMQUtils::QuorumDataRecoveryEnabled()}; const bool fQuorumVvecRequestsEnabled{llmq::CLLMQUtils::GetEnabledQuorumVvecSyncEntries().size() > 0}; if (!fRecoveryEnabled && fQuorumVvecRequestsEnabled) { - InitWarning("-llmq-qvvec-sync set but recovery is disabled due to -llmq-data-recovery=0"); + InitWarning(Untranslated("-llmq-qvvec-sync set but recovery is disabled due to -llmq-data-recovery=0")); } } catch (const std::invalid_argument& e) { return InitError(Untranslated(e.what())); } if (gArgs.IsArgSet("-maxorphantx")) { - InitWarning("-maxorphantx is not supported anymore. Use -maxorphantxsize instead."); + InitWarning(Untranslated("-maxorphantx is not supported anymore. Use -maxorphantxsize instead.")); } if (gArgs.IsArgSet("-masternode")) { - InitWarning(_("-masternode option is deprecated and ignored, specifying -masternodeblsprivkey is enough to start this node as a masternode.").translated); + InitWarning(_("-masternode option is deprecated and ignored, specifying -masternodeblsprivkey is enough to start this node as a masternode.")); } if (gArgs.IsArgSet("-masternodeblsprivkey")) { @@ -1549,7 +1549,7 @@ bool AppInitParameterInteraction() } if (gArgs.IsArgSet("-litemode")) { - InitWarning(_("-litemode is deprecated.").translated + (gArgs.GetBoolArg("-litemode", false) ? (" " + _("Its replacement -disablegovernance has been forced instead.").translated) : ( " " + _("It has been replaced by -disablegovernance.").translated))); + InitWarning(strprintf(_("-litemode is deprecated.%s"), (gArgs.GetBoolArg("-litemode", false) ? (" " + _("Its replacement -disablegovernance has been forced instead.").translated) : ( " " + _("It has been replaced by -disablegovernance.").translated)))); gArgs.ForceRemoveArg("-litemode"); } @@ -1557,7 +1557,7 @@ bool AppInitParameterInteraction() LogPrintf("fDisableGovernance %d\n", fDisableGovernance); if (fDisableGovernance) { - InitWarning(_("You are starting with governance validation disabled.").translated + (fPruneMode ? " " + _("This is expected because you are running a pruned node.").translated : "")); + InitWarning(strprintf(_("You are starting with governance validation disabled.%s"), (fPruneMode ? " " + _("This is expected because you are running a pruned node.").translated : ""))); } return true; @@ -1642,7 +1642,7 @@ bool AppInitMain(InitInterfaces& interfaces) LogPrintf("Config file: %s\n", config_file_path.string()); } else if (gArgs.IsArgSet("-conf")) { // Warn if no conf file exists at path provided by user - InitWarning(strprintf(_("The specified config file %s does not exist\n").translated, config_file_path.string())); + InitWarning(strprintf(_("The specified config file %s does not exist\n"), config_file_path.string())); } else { // Not categorizing as "Warning" because it's the default behavior LogPrintf("Config file: %s (not found, skipping)\n", config_file_path.string()); diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp index a20584e2d117..b467c3b25c88 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -344,7 +344,7 @@ class ChainImpl : public Chain bool shutdownRequested() override { return ShutdownRequested(); } int64_t getAdjustedTime() override { return GetAdjustedTime(); } void initMessage(const std::string& message) override { ::uiInterface.InitMessage(message); } - void initWarning(const std::string& message) override { InitWarning(message); } + void initWarning(const bilingual_str& message) override { InitWarning(message); } void initError(const bilingual_str& message) override { InitError(message); } void loadWallet(std::unique_ptr wallet) override { ::uiInterface.LoadWallet(wallet); } void showProgress(const std::string& title, int progress, bool resume_possible) override diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index 946c69ff8626..bfbdc6635c81 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -214,7 +214,7 @@ class Chain virtual void initMessage(const std::string& message) = 0; //! Send init warning. - virtual void initWarning(const std::string& message) = 0; + virtual void initWarning(const bilingual_str& message) = 0; //! Send init error. virtual void initError(const bilingual_str& message) = 0; diff --git a/src/qt/walletcontroller.cpp b/src/qt/walletcontroller.cpp index 1bd0d78579d5..ae573dab0276 100644 --- a/src/qt/walletcontroller.cpp +++ b/src/qt/walletcontroller.cpp @@ -232,7 +232,7 @@ void CreateWalletActivity::finish() if (!m_error_message.original.empty()) { QMessageBox::critical(m_parent_widget, tr("Create wallet failed"), QString::fromStdString(m_error_message.translated)); } else if (!m_warning_message.empty()) { - QMessageBox::warning(m_parent_widget, tr("Create wallet warning"), QString::fromStdString(Join(m_warning_message, "\n", OpTranslated))); + QMessageBox::warning(m_parent_widget, tr("Create wallet warning"), QString::fromStdString(Join(m_warning_message, Untranslated("\n")).translated)); } if (m_wallet_model) Q_EMIT created(m_wallet_model); @@ -273,7 +273,7 @@ void OpenWalletActivity::finish() if (!m_error_message.original.empty()) { QMessageBox::critical(m_parent_widget, tr("Open wallet failed"), QString::fromStdString(m_error_message.translated)); } else if (!m_warning_message.empty()) { - QMessageBox::warning(m_parent_widget, tr("Open wallet warning"), QString::fromStdString(Join(m_warning_message, "\n", OpTranslated))); + QMessageBox::warning(m_parent_widget, tr("Open wallet warning"), QString::fromStdString(Join(m_warning_message, Untranslated("\n")).translated)); } if (m_wallet_model) Q_EMIT opened(m_wallet_model); diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 2ad5985d127b..c40e1d291550 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -433,7 +433,7 @@ bool WalletModel::autoBackupWallet(QString& strBackupWarningRet, QString& strBac bilingual_str strBackupError; std::vector warnings; bool result = m_wallet->autoBackupWallet("", strBackupError, warnings); - strBackupWarningRet = QString::fromStdString(Join(warnings, "\n", OpTranslated)); + strBackupWarningRet = QString::fromStdString(Join(warnings, Untranslated("\n")).translated); strBackupErrorRet = QString::fromStdString(strBackupError.translated); return result; } diff --git a/src/ui_interface.cpp b/src/ui_interface.cpp index 10014e672fbd..bd2b7284f603 100644 --- a/src/ui_interface.cpp +++ b/src/ui_interface.cpp @@ -71,7 +71,7 @@ bool InitError(const bilingual_str& str) return false; } -void InitWarning(const std::string& str) +void InitWarning(const bilingual_str& str) { - uiInterface.ThreadSafeMessageBox(Untranslated(str), "", CClientUIInterface::MSG_WARNING); + uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_WARNING); } diff --git a/src/ui_interface.h b/src/ui_interface.h index 8c26201aa31e..72cecbf6b699 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -138,8 +138,7 @@ class CClientUIInterface }; /** Show warning message **/ -// TODO: InitWarning() should take a bilingual_str parameter. -void InitWarning(const std::string& str); +void InitWarning(const bilingual_str& str); /** Show error message **/ bool InitError(const bilingual_str& str); diff --git a/src/util/translation.h b/src/util/translation.h index b4f8fd9f3813..092317c74a55 100644 --- a/src/util/translation.h +++ b/src/util/translation.h @@ -17,21 +17,23 @@ struct bilingual_str { std::string original; std::string translated; + + bilingual_str& operator+=(const bilingual_str& rhs) + { + original += rhs.original; + translated += rhs.translated; + return *this; + } }; -inline bilingual_str operator+(const bilingual_str& lhs, const bilingual_str& rhs) +inline bilingual_str operator+(bilingual_str lhs, const bilingual_str& rhs) { - return bilingual_str{ - lhs.original + rhs.original, - lhs.translated + rhs.translated}; + lhs += rhs; + return lhs; } /** Mark a bilingual_str as untranslated */ inline bilingual_str Untranslated(std::string original) { return {original, original}; } -/** Unary operator to return the original */ -inline std::string OpOriginal(const bilingual_str& b) { return b.original; } -/** Unary operator to return the translation */ -inline std::string OpTranslated(const bilingual_str& b) { return b.translated; } namespace tinyformat { template diff --git a/src/wallet/init.cpp b/src/wallet/init.cpp index 0dcd5d914349..0a52db18f15f 100644 --- a/src/wallet/init.cpp +++ b/src/wallet/init.cpp @@ -130,7 +130,7 @@ bool WalletInit::ParameterInteraction() const int rescan_mode = gArgs.GetArg("-rescan", 0); if (rescan_mode < 0 || rescan_mode > 2) { LogPrintf("%s: Warning: incorrect -rescan mode, falling back to default value.\n", __func__); - InitWarning(_("Incorrect -rescan mode, falling back to default value").translated); + InitWarning(_("Incorrect -rescan mode, falling back to default value")); gArgs.ForceRemoveArg("-rescan"); } @@ -147,13 +147,13 @@ bool WalletInit::ParameterInteraction() const if (gArgs.IsArgSet("-walletbackupsdir")) { if (!fs::is_directory(gArgs.GetArg("-walletbackupsdir", ""))) { - InitWarning(strprintf(_("Warning: incorrect parameter %s, path must exist! Using default path.").translated, "-walletbackupsdir")); + InitWarning(strprintf(_("Warning: incorrect parameter %s, path must exist! Using default path."), "-walletbackupsdir")); gArgs.ForceRemoveArg("-walletbackupsdir"); } } if (gArgs.IsArgSet("-hdseed") && IsHex(gArgs.GetArg("-hdseed", "not hex")) && (gArgs.IsArgSet("-mnemonic") || gArgs.IsArgSet("-mnemonicpassphrase"))) { - InitWarning(strprintf(_("Warning: can't use %s and %s together, will prefer %s").translated, "-hdseed", "-mnemonic/-mnemonicpassphrase", "-hdseed")); + InitWarning(strprintf(_("Warning: can't use %s and %s together, will prefer %s"), "-hdseed", "-mnemonic/-mnemonicpassphrase", "-hdseed")); gArgs.ForceRemoveArg("-mnemonic"); gArgs.ForceRemoveArg("-mnemonicpassphrase"); } @@ -161,7 +161,7 @@ bool WalletInit::ParameterInteraction() const // begin PrivateSend -> CoinJoin migration if (gArgs.IsArgSet("-privatesendrounds")) { int nRoundsDeprecated = gArgs.GetArg("-privatesendrounds", DEFAULT_COINJOIN_ROUNDS); - InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead").translated, "-privatesendrounds", "-coinjoinrounds")); + InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead"), "-privatesendrounds", "-coinjoinrounds")); if (gArgs.SoftSetArg("-coinjoinrounds", itostr(nRoundsDeprecated))) { LogPrintf("%s: parameter interaction: -privatesendrounds=%d -> setting -coinjoinrounds=%d\n", __func__, nRoundsDeprecated, nRoundsDeprecated); } @@ -169,7 +169,7 @@ bool WalletInit::ParameterInteraction() const } if (gArgs.IsArgSet("-privatesendamount")) { int nAmountDeprecated = gArgs.GetArg("-privatesendamount", DEFAULT_COINJOIN_AMOUNT); - InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead").translated, "-privatesendamount", "-coinjoinamount")); + InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead"), "-privatesendamount", "-coinjoinamount")); if (gArgs.SoftSetArg("-coinjoinamount", itostr(nAmountDeprecated))) { LogPrintf("%s: parameter interaction: -privatesendamount=%d -> setting -coinjoinamount=%d\n", __func__, nAmountDeprecated, nAmountDeprecated); } @@ -177,7 +177,7 @@ bool WalletInit::ParameterInteraction() const } if (gArgs.IsArgSet("-privatesenddenomsgoal")) { int nDenomsGoalDeprecated = gArgs.GetArg("-privatesenddenomsgoal", DEFAULT_COINJOIN_DENOMS_GOAL); - InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead").translated, "-privatesenddenomsgoal", "-coinjoindenomsgoal")); + InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead"), "-privatesenddenomsgoal", "-coinjoindenomsgoal")); if (gArgs.SoftSetArg("-coinjoindenomsgoal", itostr(nDenomsGoalDeprecated))) { LogPrintf("%s: parameter interaction: -privatesenddenomsgoal=%d -> setting -coinjoindenomsgoal=%d\n", __func__, nDenomsGoalDeprecated, nDenomsGoalDeprecated); } @@ -185,7 +185,7 @@ bool WalletInit::ParameterInteraction() const } if (gArgs.IsArgSet("-privatesenddenomshardcap")) { int nDenomsHardcapDeprecated = gArgs.GetArg("-privatesenddenomshardcap", DEFAULT_COINJOIN_DENOMS_HARDCAP); - InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead").translated, "-privatesenddenomshardcap", "-coinjoindenomshardcap")); + InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead"), "-privatesenddenomshardcap", "-coinjoindenomshardcap")); if (gArgs.SoftSetArg("-coinjoindenomshardcap", itostr(nDenomsHardcapDeprecated))) { LogPrintf("%s: parameter interaction: -privatesenddenomshardcap=%d -> setting -coinjoindenomshardcap=%d\n", __func__, nDenomsHardcapDeprecated, nDenomsHardcapDeprecated); } @@ -193,7 +193,7 @@ bool WalletInit::ParameterInteraction() const } if (gArgs.IsArgSet("-privatesendsessions")) { int nSessionsDeprecated = gArgs.GetArg("-privatesendsessions", DEFAULT_COINJOIN_SESSIONS); - InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead").translated, "-privatesendsessions", "-coinjoinsessions")); + InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead"), "-privatesendsessions", "-coinjoinsessions")); if (gArgs.SoftSetArg("-coinjoinsessions", itostr(nSessionsDeprecated))) { LogPrintf("%s: parameter interaction: -privatesendsessions=%d -> setting -coinjoinsessions=%d\n", __func__, nSessionsDeprecated, nSessionsDeprecated); } @@ -201,7 +201,7 @@ bool WalletInit::ParameterInteraction() const } if (gArgs.IsArgSet("-enableprivatesend")) { bool fEnablePSDeprecated = gArgs.GetBoolArg("-enableprivatesend", 0); - InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead").translated, "-enableprivatesend", "-enablecoinjoin")); + InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead"), "-enableprivatesend", "-enablecoinjoin")); if (gArgs.SoftSetBoolArg("-enablecoinjoin", fEnablePSDeprecated)) { LogPrintf("%s: parameter interaction: -enableprivatesend=%d -> setting -enablecoinjoin=%d\n", __func__, fEnablePSDeprecated, fEnablePSDeprecated); } @@ -209,7 +209,7 @@ bool WalletInit::ParameterInteraction() const } if (gArgs.IsArgSet("-privatesendautostart")) { bool fAutoStartDeprecated = gArgs.GetBoolArg("-privatesendautostart", DEFAULT_COINJOIN_AUTOSTART); - InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead").translated, "-privatesendautostart", "-coinjoinautostart")); + InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead"), "-privatesendautostart", "-coinjoinautostart")); if (gArgs.SoftSetBoolArg("-coinjoinautostart", fAutoStartDeprecated)) { LogPrintf("%s: parameter interaction: -privatesendautostart=%d -> setting -coinjoinautostart=%d\n", __func__, fAutoStartDeprecated, fAutoStartDeprecated); } @@ -217,7 +217,7 @@ bool WalletInit::ParameterInteraction() const } if (gArgs.IsArgSet("-privatesendmultisession")) { bool fMultiSessionDeprecated = gArgs.GetBoolArg("-privatesendmultisession", DEFAULT_COINJOIN_MULTISESSION); - InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead").translated, "-privatesendmultisession", "-coinjoinmultisession")); + InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead"), "-privatesendmultisession", "-coinjoinmultisession")); if (gArgs.SoftSetBoolArg("-coinjoinmultisession", fMultiSessionDeprecated)) { LogPrintf("%s: parameter interaction: -privatesendmultisession=%d -> setting -coinjoinmultisession=%d\n", __func__, fMultiSessionDeprecated, fMultiSessionDeprecated); } diff --git a/src/wallet/load.cpp b/src/wallet/load.cpp index 0c915d2ce153..a0d9260cd7e5 100644 --- a/src/wallet/load.cpp +++ b/src/wallet/load.cpp @@ -54,7 +54,7 @@ bool VerifyWallets(interfaces::Chain& chain, const std::vector& wal bilingual_str error_string; std::vector warnings; bool verify_success = CWallet::Verify(chain, location, error_string, warnings); - if (!warnings.empty()) chain.initWarning(Join(warnings, "\n", OpTranslated)); + if (!warnings.empty()) chain.initWarning(Join(warnings, Untranslated("\n"))); if (!verify_success) { chain.initError(error_string); return false; @@ -70,7 +70,7 @@ bool LoadWallets(interfaces::Chain& chain, const std::vector& walle bilingual_str error_string; std::vector warnings; std::shared_ptr pwallet = CWallet::CreateWalletFromFile(chain, WalletLocation(walletFile), error_string, warnings); - if (!warnings.empty()) chain.initWarning(Join(warnings, "\n", OpTranslated)); + if (!warnings.empty()) chain.initWarning(Join(warnings, Untranslated("\n"))); if (!pwallet) { chain.initError(error_string); return false; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 5838e674b21a..924c9d2248d8 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2733,7 +2733,7 @@ static UniValue loadwallet(const JSONRPCRequest& request) UniValue obj(UniValue::VOBJ); obj.pushKV("name", wallet->GetName()); - obj.pushKV("warning", Join(warnings, "\n", OpOriginal)); + obj.pushKV("warning", Join(warnings, Untranslated("\n")).original); return obj; } @@ -2800,7 +2800,7 @@ static UniValue createwallet(const JSONRPCRequest& request) UniValue obj(UniValue::VOBJ); obj.pushKV("name", wallet->GetName()); - obj.pushKV("warning", Join(warnings, "\n", OpOriginal)); + obj.pushKV("warning", Join(warnings, Untranslated("\n")).original); return obj; } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 8cc9c10cd2df..6f81f6d024a1 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -5497,7 +5497,7 @@ bool CWallet::AutoBackupWallet(const fs::path& wallet_path, bilingual_str& error backupFile.make_preferred(); if (!BackupWallet(backupFile.string())) { warnings.push_back(strprintf(_("Failed to create backup %s!"), backupFile.string())); - WalletLogPrintf("%s\n", Join(warnings, "\n", OpTranslated)); + WalletLogPrintf("%s\n", Join(warnings, Untranslated("\n")).translated); nWalletBackups = -1; return false; } @@ -5507,7 +5507,7 @@ bool CWallet::AutoBackupWallet(const fs::path& wallet_path, bilingual_str& error WalletLogPrintf("nKeysLeftSinceAutoBackup: %d\n", nKeysLeftSinceAutoBackup); if (IsLocked(true)) { warnings.push_back(_("Wallet is locked, can't replenish keypool! Automatic backups and mixing are disabled, please unlock your wallet to replenish keypool.")); - WalletLogPrintf("%s\n", Join(warnings, "\n", OpTranslated)); + WalletLogPrintf("%s\n", Join(warnings, Untranslated("\n")).translated); nWalletBackups = -2; return false; } @@ -5522,7 +5522,7 @@ bool CWallet::AutoBackupWallet(const fs::path& wallet_path, bilingual_str& error if (fs::exists(backupFile)) { warnings.push_back(_("Failed to create backup, file already exists! This could happen if you restarted wallet in less than 60 seconds. You can continue if you are ok with this.")); - WalletLogPrintf("%s\n", Join(warnings, "\n", OpTranslated)); + WalletLogPrintf("%s\n", Join(warnings, Untranslated("\n")).translated); return false; } if(fs::exists(sourceFile)) { @@ -5531,7 +5531,7 @@ bool CWallet::AutoBackupWallet(const fs::path& wallet_path, bilingual_str& error WalletLogPrintf("Creating backup of %s -> %s\n", sourceFile.string(), backupFile.string()); } catch(fs::filesystem_error &error) { warnings.push_back(strprintf(_("Failed to create backup, error: %s"), fsbridge::get_filesystem_error_message(error))); - WalletLogPrintf("%s\n", Join(warnings, "\n", OpTranslated)); + WalletLogPrintf("%s\n", Join(warnings, Untranslated("\n")).translated); nWalletBackups = -1; return false; } @@ -5570,7 +5570,7 @@ bool CWallet::AutoBackupWallet(const fs::path& wallet_path, bilingual_str& error WalletLogPrintf("Old backup deleted: %s\n", file.second); } catch(fs::filesystem_error &error) { warnings.push_back(strprintf(_("Failed to delete backup, error: %s"), fsbridge::get_filesystem_error_message(error))); - WalletLogPrintf("%s\n", Join(warnings, "\n", OpTranslated)); + WalletLogPrintf("%s\n", Join(warnings, Untranslated("\n")).translated); return false; } } From 6e93df5db67c49703da95cc86b42a7db372ec0d1 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 22 Jul 2020 08:58:50 +0200 Subject: [PATCH 03/11] Merge #18907: walletdb: Don't remove database transaction logs and instead error d0ea9bab2804928c9f40def61fd99064d2d8f9b8 walletdb: Don't remove database transaction logs and instead error (Andrew Chow) Pull request description: Instead of removing the database transaction logs and retrying the wallet loading, just return an error message to the user. Additionally, speciically for DB_RUNRECOVERY, notify the user that this could be due to different BDB versions. Kind of implements the suggestion from https://github.com/bitcoin/bitcoin/pull/18870#discussion_r421647964 ACKs for top commit: Sjors: re-utACK d0ea9bab2804928c9f40def61fd99064d2d8f9b8 ryanofsky: Code review ACK d0ea9bab2804928c9f40def61fd99064d2d8f9b8. Only changes since last review are rebase and expanding error and commit messages. Tree-SHA512: f6e67dc70f58188742a5c8af7cdc63a2b58779aa0d26ae7f1e75805a239f1a342433860e5a238d6577fae5ab04b9d15e7f11c55b867065dfd13781a6a62e4958 --- src/wallet/bdb.cpp | 32 +++++++++++--------------------- src/wallet/bdb.h | 2 +- src/wallet/salvage.cpp | 6 ++++-- 3 files changed, 16 insertions(+), 24 deletions(-) diff --git a/src/wallet/bdb.cpp b/src/wallet/bdb.cpp index d571ddf5580e..5c1f8eb06f7c 100644 --- a/src/wallet/bdb.cpp +++ b/src/wallet/bdb.cpp @@ -139,7 +139,7 @@ BerkeleyEnvironment::~BerkeleyEnvironment() Close(); } -bool BerkeleyEnvironment::Open(bool retry) +bool BerkeleyEnvironment::Open(bilingual_str& err) { if (fDbEnvInit) { return true; @@ -149,6 +149,7 @@ bool BerkeleyEnvironment::Open(bool retry) TryCreateDirectories(pathIn); if (!LockDirectory(pathIn, ".walletlock")) { LogPrintf("Cannot obtain a lock on wallet directory %s. Another instance of bitcoin may be using it.\n", strPath); + err = strprintf(_("Error initializing wallet database environment %s!"), Directory()); return false; } @@ -188,23 +189,11 @@ bool BerkeleyEnvironment::Open(bool retry) LogPrintf("BerkeleyEnvironment::Open: Error %d closing failed database environment: %s\n", ret2, DbEnv::strerror(ret2)); } Reset(); - if (retry) { - // try moving the database env out of the way - fs::path pathDatabaseBak = pathIn / strprintf("database.%d.bak", GetTime()); - try { - fs::rename(pathLogDir, pathDatabaseBak); - LogPrintf("Moved old %s to %s. Retrying.\n", pathLogDir.string(), pathDatabaseBak.string()); - } catch (const fs::filesystem_error&) { - // failure is ok (well, not really, but it's not worse than what we started with) - } - // try opening it again one more time - if (!Open(false /* retry */)) { - // if it still fails, it probably means we can't even create the database env - return false; - } - } else { - return false; + err = strprintf(_("Error initializing wallet database environment %s!"), Directory()); + if (ret == DB_RUNRECOVERY) { + err += Untranslated(" ") + _("This error could occur if this wallet was not shutdown cleanly and was last loaded using a build with a newer version of Berkeley DB. If so, please use the software that last loaded this wallet"); } + return false; } fDbEnvInit = true; @@ -300,8 +289,7 @@ bool BerkeleyDatabase::Verify(bilingual_str& errorStr) LogPrintf("Using BerkeleyDB version %s\n", BerkeleyDatabaseVersion()); LogPrintf("Using wallet %s\n", file_path.string()); - if (!env->Open(true /* retry */)) { - errorStr = strprintf(_("Error initializing wallet database environment %s!"), walletDir); + if (!env->Open(errorStr)) { return false; } @@ -348,7 +336,8 @@ BerkeleyBatch::BerkeleyBatch(BerkeleyDatabase& database, const char* pszMode, bo { LOCK(cs_db); - if (!env->Open(false /* retry */)) + bilingual_str open_err; + if (!env->Open(open_err)) throw std::runtime_error("BerkeleyBatch: Failed to open database environment."); pdb = database.m_db.get(); @@ -489,7 +478,8 @@ void BerkeleyEnvironment::ReloadDbEnv() // Reset the environment Flush(true); // This will flush and close the environment Reset(); - Open(true); + bilingual_str open_err; + Open(open_err); } bool BerkeleyDatabase::Rewrite(const char* pszSkip) diff --git a/src/wallet/bdb.h b/src/wallet/bdb.h index 047760546bde..17c74ba423cd 100644 --- a/src/wallet/bdb.h +++ b/src/wallet/bdb.h @@ -69,7 +69,7 @@ class BerkeleyEnvironment bool Verify(const std::string& strFile); - bool Open(bool retry); + bool Open(bilingual_str& error); void Close(); void Flush(bool fShutdown); void CheckpointLSN(const std::string& strFile); diff --git a/src/wallet/salvage.cpp b/src/wallet/salvage.cpp index a786bdcfc4af..6f6b748fd259 100644 --- a/src/wallet/salvage.cpp +++ b/src/wallet/salvage.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -20,8 +21,9 @@ bool RecoverDatabaseFile(const fs::path& file_path) std::string filename; std::shared_ptr env = GetWalletEnv(file_path, filename); - if (!env->Open(true /* retry */)) { - tfm::format(std::cerr, "Error initializing wallet database environment %s!", env->Directory()); + bilingual_str open_err; + if (!env->Open(open_err)) { + tfm::format(std::cerr, "%s\n", open_err.original); return false; } From 405b44e211c0c7ee03ba038644fe6b3520d7c180 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Mon, 1 Jun 2020 18:05:15 +1000 Subject: [PATCH 04/11] merge bitcoin#19131: Fix unreachable code in init arg checks --- configure.ac | 2 ++ src/init.cpp | 16 +++++++++++++--- src/util/translation.h | 5 +++++ test/functional/feature_config_args.py | 2 +- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index ba62441596bf..2825c6845863 100644 --- a/configure.ac +++ b/configure.ac @@ -427,6 +427,7 @@ if test "x$enable_werror" = "xyes"; then dnl https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78010 AX_CHECK_COMPILE_FLAG([-Werror=suggest-override],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=suggest-override"],,[[$CXXFLAG_WERROR]], [AC_LANG_SOURCE([[struct A { virtual void f(); }; struct B : A { void f() final; };]])]) + AX_CHECK_COMPILE_FLAG([-Werror=unreachable-code-loop-increment],[ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror=unreachable-code-loop-increment"],,[[$CXXFLAG_WERROR]]) fi if test "x$CXXFLAGS_overridden" = "xno"; then @@ -445,6 +446,7 @@ if test "x$CXXFLAGS_overridden" = "xno"; then AX_CHECK_COMPILE_FLAG([-Wconditional-uninitialized],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wconditional-uninitialized"],,[[$CXXFLAG_WERROR]]) AX_CHECK_COMPILE_FLAG([-Wsuggest-override],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wsuggest-override"],,[[$CXXFLAG_WERROR]], [AC_LANG_SOURCE([[struct A { virtual void f(); }; struct B : A { void f() final; };]])]) + AX_CHECK_COMPILE_FLAG([-Wunreachable-code-loop-increment],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wunreachable-code-loop-increment"],,[[$CXXFLAG_WERROR]]) ## Some compilers (gcc) ignore unknown -Wno-* options, but warn about all ## unknown options if any other warning is produced. Test the -Wfoo case, and diff --git a/src/init.cpp b/src/init.cpp index 623ed3675980..872400abdaf1 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1262,17 +1262,27 @@ bool AppInitParameterInteraction() // also see: InitParameterInteraction() - // Warn if network-specific options (-addnode, -connect, etc) are + // Error if network-specific options (-addnode, -connect, etc) are // specified in default section of config file, but not overridden // on the command line or in this network's section of the config file. std::string network = gArgs.GetChainName(); + bilingual_str errors; for (const auto& arg : gArgs.GetUnsuitableSectionOnlyArgs()) { - return InitError(strprintf(_("Config setting for %s only applied on %s network when in [%s] section."), arg, network, network)); + errors += strprintf(_("Config setting for %s only applied on %s network when in [%s] section.") + Untranslated("\n"), arg, network, network); + } + + if (!errors.empty()) { + return InitError(errors); } // Warn if unrecognized section name are present in the config file. + bilingual_str warnings; for (const auto& section : gArgs.GetUnrecognizedSections()) { - InitWarning(strprintf(Untranslated("%s:%i ") + _("Section [%s] is not recognized."), section.m_file, section.m_line, section.m_name)); + warnings += strprintf(Untranslated("%s:%i ") + _("Section [%s] is not recognized.") + Untranslated("\n"), section.m_file, section.m_line, section.m_name); + } + + if (!warnings.empty()) { + InitWarning(warnings); } if (!fs::is_directory(GetBlocksDir())) { diff --git a/src/util/translation.h b/src/util/translation.h index 092317c74a55..c4a8c0f2b75d 100644 --- a/src/util/translation.h +++ b/src/util/translation.h @@ -24,6 +24,11 @@ struct bilingual_str { translated += rhs.translated; return *this; } + + bool empty() const + { + return original.empty(); + } }; inline bilingual_str operator+(bilingual_str lhs, const bilingual_str& rhs) diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py index 954f912c143e..315b92199fed 100755 --- a/test/functional/feature_config_args.py +++ b/test/functional/feature_config_args.py @@ -70,7 +70,7 @@ def test_config_file_parser(self): with open(inc_conf_file2_path, 'w', encoding='utf-8') as conf: conf.write('[testnet]\n') self.restart_node(0) - self.nodes[0].stop_node(expected_stderr='Warning: ' + inc_conf_file_path + ':1 Section [testnot] is not recognized.' + os.linesep + 'Warning: ' + inc_conf_file2_path + ':1 Section [testnet] is not recognized.') + self.nodes[0].stop_node(expected_stderr='Warning: ' + inc_conf_file_path + ':1 Section [testnot] is not recognized.' + os.linesep + inc_conf_file2_path + ':1 Section [testnet] is not recognized.') with open(inc_conf_file_path, 'w', encoding='utf-8') as conf: conf.write('') # clear From bc85d2d2996a05e5e0db5030d9d8beb87b2523a2 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Thu, 7 Apr 2022 13:47:19 +0530 Subject: [PATCH 05/11] merge bitcoin#19176: Error message bilingual_str consistency --- src/init.cpp | 12 ++++++------ src/interfaces/node.cpp | 2 +- src/interfaces/node.h | 2 +- src/net_permissions.cpp | 22 +++++++++++++--------- src/net_permissions.h | 9 ++++++--- src/qt/dash.cpp | 8 ++++---- src/rpc/util.cpp | 3 ++- src/test/netbase_tests.cpp | 11 ++++++----- src/util/error.cpp | 26 +++++++++++++------------- src/util/error.h | 6 ++++-- src/wallet/wallet.cpp | 2 +- 11 files changed, 57 insertions(+), 46 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 872400abdaf1..d65b431bd16b 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1866,7 +1866,7 @@ bool AppInitMain(InitInterfaces& interfaces) if (Lookup(strAddr.c_str(), addrLocal, GetListenPort(), fNameLookup) && addrLocal.IsValid()) AddLocal(addrLocal, LOCAL_MANUAL); else - return InitError(Untranslated(ResolveErrMsg("externalip", strAddr))); + return InitError(ResolveErrMsg("externalip", strAddr)); } // Read asmap file if configured @@ -2442,21 +2442,21 @@ bool AppInitMain(InitInterfaces& interfaces) for (const std::string& strBind : gArgs.GetArgs("-bind")) { CService addrBind; if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false)) { - return InitError(Untranslated(ResolveErrMsg("bind", strBind))); + return InitError(ResolveErrMsg("bind", strBind)); } connOptions.vBinds.push_back(addrBind); } for (const std::string& strBind : gArgs.GetArgs("-whitebind")) { NetWhitebindPermissions whitebind; - std::string error; - if (!NetWhitebindPermissions::TryParse(strBind, whitebind, error)) return InitError(Untranslated(error)); + bilingual_str error; + if (!NetWhitebindPermissions::TryParse(strBind, whitebind, error)) return InitError(error); connOptions.vWhiteBinds.push_back(whitebind); } for (const auto& net : gArgs.GetArgs("-whitelist")) { NetWhitelistPermissions subnet; - std::string error; - if (!NetWhitelistPermissions::TryParse(net, subnet, error)) return InitError(Untranslated(error)); + bilingual_str error; + if (!NetWhitelistPermissions::TryParse(net, subnet, error)) return InitError(error); connOptions.vWhitelistedRange.push_back(subnet); } diff --git a/src/interfaces/node.cpp b/src/interfaces/node.cpp index e818f3fb66c3..05c4e7250588 100644 --- a/src/interfaces/node.cpp +++ b/src/interfaces/node.cpp @@ -178,7 +178,7 @@ class NodeImpl : public Node MasternodeSyncImpl m_masternodeSync; CoinJoinOptionsImpl m_coinjoin; - void initError(const std::string& message) override { InitError(Untranslated(message)); } + void initError(const bilingual_str& message) override { InitError(message); } bool parseParameters(int argc, const char* const argv[], std::string& error) override { return gArgs.ParseParameters(argc, argv, error); diff --git a/src/interfaces/node.h b/src/interfaces/node.h index 1cb96f358e87..95177dec1da3 100644 --- a/src/interfaces/node.h +++ b/src/interfaces/node.h @@ -106,7 +106,7 @@ class Node virtual ~Node() {} //! Send init error. - virtual void initError(const std::string& message) = 0; + virtual void initError(const bilingual_str& message) = 0; //! Set command line arguments. virtual bool parseParameters(int argc, const char* const argv[], std::string& error) = 0; diff --git a/src/net_permissions.cpp b/src/net_permissions.cpp index ef6c40ce207a..5f5e0ee8a306 100644 --- a/src/net_permissions.cpp +++ b/src/net_permissions.cpp @@ -8,8 +8,10 @@ #include #include +namespace { + // The parse the following format "perm1,perm2@xxxxxx" -bool TryParsePermissionFlags(const std::string str, NetPermissionFlags& output, size_t& readen, std::string& error) +bool TryParsePermissionFlags(const std::string str, NetPermissionFlags& output, size_t& readen, bilingual_str& error) { NetPermissionFlags flags = PF_NONE; const auto atSeparator = str.find('@'); @@ -40,7 +42,7 @@ bool TryParsePermissionFlags(const std::string str, NetPermissionFlags& output, else if (permission == "relay") NetPermissions::AddFlag(flags, PF_RELAY); else if (permission.length() == 0); // Allow empty entries else { - error = strprintf(_("Invalid P2P permission: '%s'").translated, permission); + error = strprintf(_("Invalid P2P permission: '%s'"), permission); return false; } } @@ -48,10 +50,12 @@ bool TryParsePermissionFlags(const std::string str, NetPermissionFlags& output, } output = flags; - error = ""; + error = Untranslated(""); return true; } +} + std::vector NetPermissions::ToStrings(NetPermissionFlags flags) { std::vector strings; @@ -63,7 +67,7 @@ std::vector NetPermissions::ToStrings(NetPermissionFlags flags) return strings; } -bool NetWhitebindPermissions::TryParse(const std::string str, NetWhitebindPermissions& output, std::string& error) +bool NetWhitebindPermissions::TryParse(const std::string str, NetWhitebindPermissions& output, bilingual_str& error) { NetPermissionFlags flags; size_t offset; @@ -76,17 +80,17 @@ bool NetWhitebindPermissions::TryParse(const std::string str, NetWhitebindPermis return false; } if (addrBind.GetPort() == 0) { - error = strprintf(_("Need to specify a port with -whitebind: '%s'").translated, strBind); + error = strprintf(_("Need to specify a port with -whitebind: '%s'"), strBind); return false; } output.m_flags = flags; output.m_service = addrBind; - error = ""; + error = Untranslated(""); return true; } -bool NetWhitelistPermissions::TryParse(const std::string str, NetWhitelistPermissions& output, std::string& error) +bool NetWhitelistPermissions::TryParse(const std::string str, NetWhitelistPermissions& output, bilingual_str& error) { NetPermissionFlags flags; size_t offset; @@ -96,12 +100,12 @@ bool NetWhitelistPermissions::TryParse(const std::string str, NetWhitelistPermis CSubNet subnet; LookupSubNet(net.c_str(), subnet); if (!subnet.IsValid()) { - error = strprintf(_("Invalid netmask specified in -whitelist: '%s'").translated, net); + error = strprintf(_("Invalid netmask specified in -whitelist: '%s'"), net); return false; } output.m_flags = flags; output.m_subnet = subnet; - error = ""; + error = Untranslated(""); return true; } diff --git a/src/net_permissions.h b/src/net_permissions.h index b3987de65f75..3edbdeea4d8e 100644 --- a/src/net_permissions.h +++ b/src/net_permissions.h @@ -8,6 +8,9 @@ #ifndef BITCOIN_NET_PERMISSIONS_H #define BITCOIN_NET_PERMISSIONS_H + +struct bilingual_str; + enum NetPermissionFlags { PF_NONE = 0, @@ -48,15 +51,15 @@ class NetPermissions class NetWhitebindPermissions : public NetPermissions { public: - static bool TryParse(const std::string str, NetWhitebindPermissions& output, std::string& error); + static bool TryParse(const std::string str, NetWhitebindPermissions& output, bilingual_str& error); CService m_service; }; class NetWhitelistPermissions : public NetPermissions { public: - static bool TryParse(const std::string str, NetWhitelistPermissions& output, std::string& error); + static bool TryParse(const std::string str, NetWhitelistPermissions& output, bilingual_str& error); CSubNet m_subnet; }; -#endif // BITCOIN_NET_PERMISSIONS_H \ No newline at end of file +#endif // BITCOIN_NET_PERMISSIONS_H diff --git a/src/qt/dash.cpp b/src/qt/dash.cpp index a1ebb795a955..1d6a7cc4a692 100644 --- a/src/qt/dash.cpp +++ b/src/qt/dash.cpp @@ -478,7 +478,7 @@ int GuiMain(int argc, char* argv[]) SetupUIArgs(); std::string error; if (!node->parseParameters(argc, argv, error)) { - node->initError(strprintf("Error parsing command line arguments: %s\n", error)); + node->initError(strprintf(Untranslated("Error parsing command line arguments: %s\n"), error)); // Create a message box, because the gui has neither been created nor has subscribed to core signals QMessageBox::critical(nullptr, PACKAGE_NAME, // message can not be translated because translations have not been initialized @@ -525,13 +525,13 @@ int GuiMain(int argc, char* argv[]) /// - Do not call GetDataDir(true) before this step finishes if (!fs::is_directory(GetDataDir(false))) { - node->initError(strprintf("Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", ""))); + node->initError(strprintf(Untranslated("Specified data directory \"%s\" does not exist.\n"), gArgs.GetArg("-datadir", ""))); QMessageBox::critical(nullptr, PACKAGE_NAME, QObject::tr("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(gArgs.GetArg("-datadir", "")))); return EXIT_FAILURE; } if (!node->readConfigFiles(error)) { - node->initError(strprintf("Error reading configuration file: %s\n", error)); + node->initError(strprintf(Untranslated("Error reading configuration file: %s\n"), error)); QMessageBox::critical(nullptr, PACKAGE_NAME, QObject::tr("Error: Cannot parse configuration file: %1.").arg(QString::fromStdString(error))); return EXIT_FAILURE; @@ -547,7 +547,7 @@ int GuiMain(int argc, char* argv[]) try { node->selectParams(gArgs.GetChainName()); } catch(std::exception &e) { - node->initError(strprintf("%s\n", e.what())); + node->initError(Untranslated(strprintf("%s\n", e.what()))); QMessageBox::critical(nullptr, PACKAGE_NAME, QObject::tr("Error: %1").arg(e.what())); return EXIT_FAILURE; } diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp index ade02f36add7..d69ae6fc3211 100644 --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include @@ -816,7 +817,7 @@ UniValue JSONRPCTransactionError(TransactionError terr, const std::string& err_s if (err_string.length() > 0) { return JSONRPCError(RPCErrorFromTransactionError(terr), err_string); } else { - return JSONRPCError(RPCErrorFromTransactionError(terr), TransactionErrorString(terr)); + return JSONRPCError(RPCErrorFromTransactionError(terr), TransactionErrorString(terr).original); } } diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index dcd199b2b701..bce84e4b6c8f 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -452,15 +453,15 @@ BOOST_AUTO_TEST_CASE(netbase_parsenetwork) BOOST_AUTO_TEST_CASE(netpermissions_test) { - std::string error; + bilingual_str error; NetWhitebindPermissions whitebindPermissions; NetWhitelistPermissions whitelistPermissions; // Detect invalid white bind BOOST_CHECK(!NetWhitebindPermissions::TryParse("", whitebindPermissions, error)); - BOOST_CHECK(error.find("Cannot resolve -whitebind address") != std::string::npos); + BOOST_CHECK(error.original.find("Cannot resolve -whitebind address") != std::string::npos); BOOST_CHECK(!NetWhitebindPermissions::TryParse("127.0.0.1", whitebindPermissions, error)); - BOOST_CHECK(error.find("Need to specify a port with -whitebind") != std::string::npos); + BOOST_CHECK(error.original.find("Need to specify a port with -whitebind") != std::string::npos); BOOST_CHECK(!NetWhitebindPermissions::TryParse("", whitebindPermissions, error)); // If no permission flags, assume backward compatibility @@ -504,11 +505,11 @@ BOOST_AUTO_TEST_CASE(netpermissions_test) // Detect invalid flag BOOST_CHECK(!NetWhitebindPermissions::TryParse("bloom,forcerelay,oopsie@1.2.3.4:32", whitebindPermissions, error)); - BOOST_CHECK(error.find("Invalid P2P permission") != std::string::npos); + BOOST_CHECK(error.original.find("Invalid P2P permission") != std::string::npos); // Check whitelist error BOOST_CHECK(!NetWhitelistPermissions::TryParse("bloom,forcerelay,noban@1.2.3.4:32", whitelistPermissions, error)); - BOOST_CHECK(error.find("Invalid netmask specified in -whitelist") != std::string::npos); + BOOST_CHECK(error.original.find("Invalid netmask specified in -whitelist") != std::string::npos); // Happy path for whitelist parsing BOOST_CHECK(NetWhitelistPermissions::TryParse("noban@1.2.3.4", whitelistPermissions, error)); diff --git a/src/util/error.cpp b/src/util/error.cpp index 287476c0d3ce..78e93b9e6cd7 100644 --- a/src/util/error.cpp +++ b/src/util/error.cpp @@ -8,37 +8,37 @@ #include #include -std::string TransactionErrorString(const TransactionError err) +bilingual_str TransactionErrorString(const TransactionError err) { switch (err) { case TransactionError::OK: - return "No error"; + return Untranslated("No error"); case TransactionError::MISSING_INPUTS: - return "Missing inputs"; + return Untranslated("Missing inputs"); case TransactionError::ALREADY_IN_CHAIN: - return "Transaction already in block chain"; + return Untranslated("Transaction already in block chain"); case TransactionError::P2P_DISABLED: - return "Peer-to-peer functionality missing or disabled"; + return Untranslated("Peer-to-peer functionality missing or disabled"); case TransactionError::MEMPOOL_REJECTED: - return "Transaction rejected by AcceptToMemoryPool"; + return Untranslated("Transaction rejected by AcceptToMemoryPool"); case TransactionError::MEMPOOL_ERROR: - return "AcceptToMemoryPool failed"; + return Untranslated("AcceptToMemoryPool failed"); case TransactionError::INVALID_PSBT: - return "PSBT is not sane"; + return Untranslated("PSBT is not sane"); case TransactionError::PSBT_MISMATCH: - return "PSBTs not compatible (different transactions)"; + return Untranslated("PSBTs not compatible (different transactions)"); case TransactionError::SIGHASH_MISMATCH: - return "Specified sighash value does not match existing value"; + return Untranslated("Specified sighash value does not match existing value"); case TransactionError::MAX_FEE_EXCEEDED: - return "Fee exceeds maximum configured by -maxtxfee"; + return Untranslated("Fee exceeds maximum configured by -maxtxfee"); // no default case, so the compiler can warn about missing cases } assert(false); } -std::string ResolveErrMsg(const std::string& optname, const std::string& strBind) +bilingual_str ResolveErrMsg(const std::string& optname, const std::string& strBind) { - return strprintf(_("Cannot resolve -%s address: '%s'").translated, optname, strBind); + return strprintf(_("Cannot resolve -%s address: '%s'"), optname, strBind); } std::string AmountHighWarn(const std::string& optname) diff --git a/src/util/error.h b/src/util/error.h index 7777cc0c5d0c..edab891a41e2 100644 --- a/src/util/error.h +++ b/src/util/error.h @@ -17,6 +17,8 @@ #include +struct bilingual_str; + enum class TransactionError { OK, //!< No error MISSING_INPUTS, @@ -30,9 +32,9 @@ enum class TransactionError { MAX_FEE_EXCEEDED, }; -std::string TransactionErrorString(const TransactionError error); +bilingual_str TransactionErrorString(const TransactionError error); -std::string ResolveErrMsg(const std::string& optname, const std::string& strBind); +bilingual_str ResolveErrMsg(const std::string& optname, const std::string& strBind); std::string AmountHighWarn(const std::string& optname); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 6f81f6d024a1..de074588b363 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4037,7 +4037,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std } if (nFeeRet > m_default_max_tx_fee) { - error = Untranslated(TransactionErrorString(TransactionError::MAX_FEE_EXCEEDED)); + error = TransactionErrorString(TransactionError::MAX_FEE_EXCEEDED); return false; } From 924b8fe34b674f46908f23df3cf6b05fc2c6527e Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Sun, 10 May 2020 11:42:11 +0300 Subject: [PATCH 06/11] merge bitcoin#18927: Pass bilingual_str argument to AbortNode() --- src/noui.cpp | 28 ++++++++++++---------------- src/qt/bitcoingui.cpp | 7 ++----- src/qt/walletcontroller.cpp | 4 ++-- src/ui_interface.h | 3 --- src/validation.cpp | 24 ++++++++++++------------ 5 files changed, 28 insertions(+), 38 deletions(-) diff --git a/src/noui.cpp b/src/noui.cpp index c994bc1d8e78..36a0166a2a65 100644 --- a/src/noui.cpp +++ b/src/noui.cpp @@ -23,24 +23,20 @@ bool noui_ThreadSafeMessageBox(const bilingual_str& message, const std::string& { bool fSecure = style & CClientUIInterface::SECURE; style &= ~CClientUIInterface::SECURE; - bool prefix = !(style & CClientUIInterface::MSG_NOPREFIX); - style &= ~CClientUIInterface::MSG_NOPREFIX; std::string strCaption; - if (prefix) { - switch (style) { - case CClientUIInterface::MSG_ERROR: - strCaption = "Error: "; - break; - case CClientUIInterface::MSG_WARNING: - strCaption = "Warning: "; - break; - case CClientUIInterface::MSG_INFORMATION: - strCaption = "Information: "; - break; - default: - strCaption = caption + ": "; // Use supplied caption (can be empty) - } + switch (style) { + case CClientUIInterface::MSG_ERROR: + strCaption = "Error: "; + break; + case CClientUIInterface::MSG_WARNING: + strCaption = "Warning: "; + break; + case CClientUIInterface::MSG_INFORMATION: + strCaption = "Information: "; + break; + default: + strCaption = caption + ": "; // Use supplied caption (can be empty) } if (!fSecure) { diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 671edf833d26..9ad2969e3a2d 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -1503,9 +1503,6 @@ void BitcoinGUI::message(const QString& title, QString message, unsigned int sty int nMBoxIcon = QMessageBox::Information; int nNotifyIcon = Notificator::Information; - bool prefix = !(style & CClientUIInterface::MSG_NOPREFIX); - style &= ~CClientUIInterface::MSG_NOPREFIX; - QString msgType; if (!title.isEmpty()) { msgType = title; @@ -1513,11 +1510,11 @@ void BitcoinGUI::message(const QString& title, QString message, unsigned int sty switch (style) { case CClientUIInterface::MSG_ERROR: msgType = tr("Error"); - if (prefix) message = tr("Error: %1").arg(message); + message = tr("Error: %1").arg(message); break; case CClientUIInterface::MSG_WARNING: msgType = tr("Warning"); - if (prefix) message = tr("Warning: %1").arg(message); + message = tr("Warning: %1").arg(message); break; case CClientUIInterface::MSG_INFORMATION: msgType = tr("Information"); diff --git a/src/qt/walletcontroller.cpp b/src/qt/walletcontroller.cpp index ae573dab0276..fe732e1f9c29 100644 --- a/src/qt/walletcontroller.cpp +++ b/src/qt/walletcontroller.cpp @@ -229,7 +229,7 @@ void CreateWalletActivity::finish() { m_progress_dialog->hide(); - if (!m_error_message.original.empty()) { + if (!m_error_message.empty()) { QMessageBox::critical(m_parent_widget, tr("Create wallet failed"), QString::fromStdString(m_error_message.translated)); } else if (!m_warning_message.empty()) { QMessageBox::warning(m_parent_widget, tr("Create wallet warning"), QString::fromStdString(Join(m_warning_message, Untranslated("\n")).translated)); @@ -270,7 +270,7 @@ void OpenWalletActivity::finish() { m_progress_dialog->hide(); - if (!m_error_message.original.empty()) { + if (!m_error_message.empty()) { QMessageBox::critical(m_parent_widget, tr("Open wallet failed"), QString::fromStdString(m_error_message.translated)); } else if (!m_warning_message.empty()) { QMessageBox::warning(m_parent_widget, tr("Open wallet warning"), QString::fromStdString(Join(m_warning_message, Untranslated("\n")).translated)); diff --git a/src/ui_interface.h b/src/ui_interface.h index 72cecbf6b699..b3fec1984b67 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -72,9 +72,6 @@ class CClientUIInterface /** Force blocking, modal message box dialog (not just OS notification) */ MODAL = 0x10000000U, - /** Do not prepend error/warning prefix */ - MSG_NOPREFIX = 0x20000000U, - /** Do not print contents of message to debug log */ SECURE = 0x40000000U, diff --git a/src/validation.cpp b/src/validation.cpp index f897c6c2033e..105e1cc8a122 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1573,24 +1573,24 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex) return true; } +constexpr auto AbortError = InitError; + /** Abort with a message */ -// TODO: AbortNode() should take bilingual_str userMessage parameter. -static bool AbortNode(const std::string& strMessage, const std::string& userMessage = "", unsigned int prefix = 0) +static bool AbortNode(const std::string& strMessage, bilingual_str user_message = bilingual_str()) { SetMiscWarning(strMessage); LogPrintf("*** %s\n", strMessage); - if (!userMessage.empty()) { - uiInterface.ThreadSafeMessageBox(Untranslated(userMessage), "", CClientUIInterface::MSG_ERROR | prefix); - } else { - uiInterface.ThreadSafeMessageBox(_("Error: A fatal internal error occurred, see debug.log for details"), "", CClientUIInterface::MSG_ERROR | CClientUIInterface::MSG_NOPREFIX); + if (user_message.empty()) { + user_message = _("A fatal internal error occurred, see debug.log for details"); } + AbortError(user_message); StartShutdown(); return false; } -static bool AbortNode(CValidationState& state, const std::string& strMessage, const std::string& userMessage = "", unsigned int prefix = 0) +static bool AbortNode(CValidationState& state, const std::string& strMessage, const bilingual_str& userMessage = bilingual_str()) { - AbortNode(strMessage, userMessage, prefix); + AbortNode(strMessage, userMessage); return state.Error(strMessage); } @@ -2514,7 +2514,7 @@ bool CChainState::FlushStateToDisk( if (fDoFullFlush || fPeriodicWrite) { // Depend on nMinDiskSpace to ensure we can write block index if (!CheckDiskSpace(GetBlocksDir())) { - return AbortNode(state, "Disk space is too low!", _("Error: Disk space is too low!").translated, CClientUIInterface::MSG_NOPREFIX); + return AbortNode(state, "Disk space is too low!", _("Disk space is too low!")); } // First make sure all block and undo data is flushed to disk. { @@ -2563,7 +2563,7 @@ bool CChainState::FlushStateToDisk( // an overestimation, as most will delete an existing entry or // overwrite one. Still, use a conservative safety factor of 2. if (!CheckDiskSpace(GetDataDir(), 48 * 2 * 2 * CoinsTip().GetCacheSize())) { - return AbortNode(state, "Disk space is too low!", _("Error: Disk space is too low!").translated, CClientUIInterface::MSG_NOPREFIX); + return AbortNode(state, "Disk space is too low!", _("Disk space is too low!")); } // Flush the chainstate (which may refer to block index entries). if (!CoinsTip().Flush()) @@ -3671,7 +3671,7 @@ static bool FindBlockPos(FlatFilePos &pos, unsigned int nAddSize, unsigned int n bool out_of_space; size_t bytes_allocated = BlockFileSeq().Allocate(pos, nAddSize, out_of_space); if (out_of_space) { - return AbortNode("Disk space is too low!", _("Error: Disk space is too low!").translated, CClientUIInterface::MSG_NOPREFIX); + return AbortNode("Disk space is too low!", _("Disk space is too low!")); } if (bytes_allocated != 0 && fPruneMode) { fCheckForPruning = true; @@ -3695,7 +3695,7 @@ static bool FindUndoPos(CValidationState &state, int nFile, FlatFilePos &pos, un bool out_of_space; size_t bytes_allocated = UndoFileSeq().Allocate(pos, nAddSize, out_of_space); if (out_of_space) { - return AbortNode(state, "Disk space is too low!", _("Error: Disk space is too low!").translated, CClientUIInterface::MSG_NOPREFIX); + return AbortNode(state, "Disk space is too low!", _("Disk space is too low!")); } if (bytes_allocated != 0 && fPruneMode) { fCheckForPruning = true; From 7adf0c47570bb0ff8a3a7f541180bbd32ea4d6b4 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Tue, 16 Jun 2020 11:02:46 -0400 Subject: [PATCH 07/11] merge bitcoin#19295: Use AbortError in FatalError --- src/index/base.cpp | 6 ++---- src/ui_interface.h | 1 + src/validation.cpp | 2 -- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/index/base.cpp b/src/index/base.cpp index 8ff841082bce..6d1ed6ec379f 100644 --- a/src/index/base.cpp +++ b/src/index/base.cpp @@ -16,15 +16,13 @@ constexpr char DB_BEST_BLOCK = 'B'; constexpr int64_t SYNC_LOG_INTERVAL = 30; // seconds constexpr int64_t SYNC_LOCATOR_WRITE_INTERVAL = 30; // seconds -template +template static void FatalError(const char* fmt, const Args&... args) { std::string strMessage = tfm::format(fmt, args...); SetMiscWarning(strMessage); LogPrintf("*** %s\n", strMessage); - uiInterface.ThreadSafeMessageBox( - Untranslated("Error: A fatal internal error occurred, see debug.log for details"), - "", CClientUIInterface::MSG_ERROR); + AbortError(_("A fatal internal error occurred, see debug.log for details")); StartShutdown(); } diff --git a/src/ui_interface.h b/src/ui_interface.h index b3fec1984b67..b03df680ee44 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -139,6 +139,7 @@ void InitWarning(const bilingual_str& str); /** Show error message **/ bool InitError(const bilingual_str& str); +constexpr auto AbortError = InitError; extern CClientUIInterface uiInterface; diff --git a/src/validation.cpp b/src/validation.cpp index 105e1cc8a122..32a628e665c4 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1573,8 +1573,6 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex) return true; } -constexpr auto AbortError = InitError; - /** Abort with a message */ static bool AbortNode(const std::string& strMessage, bilingual_str user_message = bilingual_str()) { From 137bc439f5cbfeac870fac6e2e86dfc8f21d6aa0 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 7 Apr 2022 22:19:38 +0300 Subject: [PATCH 08/11] fix 16224 --- src/init.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index d65b431bd16b..47d762c02c9c 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1428,7 +1428,7 @@ bool AppInitParameterInteraction() { CAmount n = 0; if (!ParseMoney(gArgs.GetArg("-incrementalrelayfee", ""), n)) - return InitError(Untranslated(AmountErrMsg("incrementalrelayfee", gArgs.GetArg("-incrementalrelayfee", "")))); + return InitError(AmountErrMsg("incrementalrelayfee", gArgs.GetArg("-incrementalrelayfee", ""))); incrementalRelayFee = CFeeRate(n); } @@ -1470,7 +1470,7 @@ bool AppInitParameterInteraction() if (gArgs.IsArgSet("-minrelaytxfee")) { CAmount n = 0; if (!ParseMoney(gArgs.GetArg("-minrelaytxfee", ""), n)) { - return InitError(Untranslated(AmountErrMsg("minrelaytxfee", gArgs.GetArg("-minrelaytxfee", "")))); + return InitError(AmountErrMsg("minrelaytxfee", gArgs.GetArg("-minrelaytxfee", ""))); } // High fee check is done afterward in CWallet::CreateWalletFromFile() ::minRelayTxFee = CFeeRate(n); @@ -1486,7 +1486,7 @@ bool AppInitParameterInteraction() { CAmount n = 0; if (!ParseMoney(gArgs.GetArg("-blockmintxfee", ""), n)) - return InitError(Untranslated(AmountErrMsg("blockmintxfee", gArgs.GetArg("-blockmintxfee", "")))); + return InitError(AmountErrMsg("blockmintxfee", gArgs.GetArg("-blockmintxfee", ""))); } // Feerate used to define dust. Shouldn't be changed lightly as old @@ -1495,7 +1495,7 @@ bool AppInitParameterInteraction() { CAmount n = 0; if (!ParseMoney(gArgs.GetArg("-dustrelayfee", ""), n)) - return InitError(Untranslated(AmountErrMsg("dustrelayfee", gArgs.GetArg("-dustrelayfee", "")))); + return InitError(AmountErrMsg("dustrelayfee", gArgs.GetArg("-dustrelayfee", ""))); dustRelayFee = CFeeRate(n); } From c31d7e3beb98ea029745e4471b1d8705f7761d11 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 3 Sep 2019 16:23:38 +0200 Subject: [PATCH 09/11] Merge #16745: wallet: Translate all initErrors in CreateWalletFromFile fa61365a1368f9970fa22fb96f89f4ecc08e69f0 wallet: Translate all initErrors in CreateWalletFromFile (MarcoFalke) fa70d199d0c2182d76b2a1cfa21f9ada4bb12913 util: Make util/error bilingual_str (refactor) (MarcoFalke) Pull request description: The translations are going to close in three days (#15940), so I am submitting this as a standalone pull request. Those changes are part of a bugfix #16661, which includes a test. The first change (the refactor) is required, the second commit is not. I am happy to drop it, if needed. ACKs for top commit: laanwj: utACK fa61365a1368f9970fa22fb96f89f4ecc08e69f0 hebasto: ACK fa61365a1368f9970fa22fb96f89f4ecc08e69f0, I have tested the code on Linux Mint 19.2. Tree-SHA512: a7616cc38b9ffd301c6b915ea808a65815c3d97e9f57ec091772eb260e5cf0d75a13a6e4dfa3913e236833677c7929b9a748cb7d7a0e406d51749944b614e11b --- src/util/error.cpp | 8 ++++---- src/util/error.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/util/error.cpp b/src/util/error.cpp index 78e93b9e6cd7..51dd22b6ab2f 100644 --- a/src/util/error.cpp +++ b/src/util/error.cpp @@ -41,12 +41,12 @@ bilingual_str ResolveErrMsg(const std::string& optname, const std::string& strBi return strprintf(_("Cannot resolve -%s address: '%s'"), optname, strBind); } -std::string AmountHighWarn(const std::string& optname) +bilingual_str AmountHighWarn(const std::string& optname) { - return strprintf(_("%s is set very high!").translated, optname); + return strprintf(_("%s is set very high!"), optname); } -std::string AmountErrMsg(const std::string& optname, const std::string& strValue) +bilingual_str AmountErrMsg(const std::string& optname, const std::string& strValue) { - return strprintf(_("Invalid amount for -%s=: '%s'").translated, optname, strValue); + return strprintf(_("Invalid amount for -%s=: '%s'"), optname, strValue); } diff --git a/src/util/error.h b/src/util/error.h index edab891a41e2..86730ad28f72 100644 --- a/src/util/error.h +++ b/src/util/error.h @@ -36,8 +36,8 @@ bilingual_str TransactionErrorString(const TransactionError error); bilingual_str ResolveErrMsg(const std::string& optname, const std::string& strBind); -std::string AmountHighWarn(const std::string& optname); +bilingual_str AmountHighWarn(const std::string& optname); -std::string AmountErrMsg(const std::string& optname, const std::string& strValue); +bilingual_str AmountErrMsg(const std::string& optname, const std::string& strValue); #endif // BITCOIN_UTIL_ERROR_H From e67fde03aa7ea327068442706376afd9dd5179b6 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 7 Apr 2022 22:42:49 +0300 Subject: [PATCH 10/11] 16745+18699 followup --- src/wallet/wallet.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index de074588b363..4089ba78d85f 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -5219,11 +5219,11 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, if (gArgs.IsArgSet("-mintxfee")) { CAmount n = 0; if (!ParseMoney(gArgs.GetArg("-mintxfee", ""), n) || 0 == n) { - error = Untranslated(AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", ""))); + error = AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", "")); return nullptr; } if (n > HIGH_TX_FEE_PER_KB) { - warnings.push_back(Untranslated(AmountHighWarn("-mintxfee")) + Untranslated(" ") + + warnings.push_back(AmountHighWarn("-mintxfee") + Untranslated(" ") + _("This is the minimum transaction fee you pay on every transaction.")); } walletInstance->m_min_fee = CFeeRate(n); @@ -5237,7 +5237,7 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, return nullptr; } if (nFeePerK > HIGH_TX_FEE_PER_KB) { - warnings.push_back(Untranslated(AmountHighWarn("-fallbackfee")) + Untranslated(" ") + + warnings.push_back(AmountHighWarn("-fallbackfee") + Untranslated(" ") + _("This is the transaction fee you may pay when fee estimates are not available.")); } walletInstance->m_fallback_fee = CFeeRate(nFeePerK); @@ -5250,7 +5250,7 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, return nullptr; } if (nFeePerK > HIGH_TX_FEE_PER_KB) { - warnings.push_back(Untranslated(AmountHighWarn("-discardfee")) + Untranslated(" ") + + warnings.push_back(AmountHighWarn("-discardfee") + Untranslated(" ") + _("This is the transaction fee you may discard if change is smaller than dust at this level")); } walletInstance->m_discard_rate = CFeeRate(nFeePerK); @@ -5258,11 +5258,11 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, if (gArgs.IsArgSet("-paytxfee")) { CAmount nFeePerK = 0; if (!ParseMoney(gArgs.GetArg("-paytxfee", ""), nFeePerK)) { - error = Untranslated(AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", ""))); + error = AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", "")); return nullptr; } if (nFeePerK > HIGH_TX_FEE_PER_KB) { - warnings.push_back(Untranslated(AmountHighWarn("-paytxfee")) + Untranslated(" ") + + warnings.push_back(AmountHighWarn("-paytxfee") + Untranslated(" ") + _("This is the transaction fee you will pay if you send a transaction.")); } walletInstance->m_pay_tx_fee = CFeeRate(nFeePerK, 1000); @@ -5276,7 +5276,7 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, if (gArgs.IsArgSet("-maxtxfee")) { CAmount nMaxFee = 0; if (!ParseMoney(gArgs.GetArg("-maxtxfee", ""), nMaxFee)) { - error = Untranslated(AmountErrMsg("maxtxfee", gArgs.GetArg("-maxtxfee", ""))); + error = AmountErrMsg("maxtxfee", gArgs.GetArg("-maxtxfee", "")); return nullptr; } if (nMaxFee > HIGH_MAX_TX_FEE) { @@ -5291,7 +5291,7 @@ std::shared_ptr CWallet::CreateWalletFromFile(interfaces::Chain& chain, } if (chain.relayMinFee().GetFeePerK() > HIGH_TX_FEE_PER_KB) - warnings.push_back(Untranslated(AmountHighWarn("-minrelaytxfee")) + Untranslated(" ") + + warnings.push_back(AmountHighWarn("-minrelaytxfee") + Untranslated(" ") + _("The wallet will avoid paying less than the minimum relay fee.")); walletInstance->m_confirm_target = gArgs.GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET); From e425a911a786a42169e631c0ff4f347af4621ae3 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 7 Apr 2022 22:19:02 +0300 Subject: [PATCH 11/11] tweak 18922 should avoiid changing translated strings when possible should NOT translate debug.log messsages --- src/init.cpp | 10 ++++++++-- src/wallet/wallet.cpp | 10 +++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 47d762c02c9c..f3b46e24123b 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1559,7 +1559,10 @@ bool AppInitParameterInteraction() } if (gArgs.IsArgSet("-litemode")) { - InitWarning(strprintf(_("-litemode is deprecated.%s"), (gArgs.GetBoolArg("-litemode", false) ? (" " + _("Its replacement -disablegovernance has been forced instead.").translated) : ( " " + _("It has been replaced by -disablegovernance.").translated)))); + InitWarning(_("-litemode is deprecated.") + + (gArgs.GetBoolArg("-litemode", false) ? + (Untranslated(" ") + _("Its replacement -disablegovernance has been forced instead.")) : + (Untranslated(" ") + _("It has been replaced by -disablegovernance.")))); gArgs.ForceRemoveArg("-litemode"); } @@ -1567,7 +1570,10 @@ bool AppInitParameterInteraction() LogPrintf("fDisableGovernance %d\n", fDisableGovernance); if (fDisableGovernance) { - InitWarning(strprintf(_("You are starting with governance validation disabled.%s"), (fPruneMode ? " " + _("This is expected because you are running a pruned node.").translated : ""))); + InitWarning(_("You are starting with governance validation disabled.") + + (fPruneMode ? + Untranslated(" ") + _("This is expected because you are running a pruned node.") : + Untranslated(""))); } return true; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 4089ba78d85f..f6b7c778c51b 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -5497,7 +5497,7 @@ bool CWallet::AutoBackupWallet(const fs::path& wallet_path, bilingual_str& error backupFile.make_preferred(); if (!BackupWallet(backupFile.string())) { warnings.push_back(strprintf(_("Failed to create backup %s!"), backupFile.string())); - WalletLogPrintf("%s\n", Join(warnings, Untranslated("\n")).translated); + WalletLogPrintf("%s\n", Join(warnings, Untranslated("\n")).original); nWalletBackups = -1; return false; } @@ -5507,7 +5507,7 @@ bool CWallet::AutoBackupWallet(const fs::path& wallet_path, bilingual_str& error WalletLogPrintf("nKeysLeftSinceAutoBackup: %d\n", nKeysLeftSinceAutoBackup); if (IsLocked(true)) { warnings.push_back(_("Wallet is locked, can't replenish keypool! Automatic backups and mixing are disabled, please unlock your wallet to replenish keypool.")); - WalletLogPrintf("%s\n", Join(warnings, Untranslated("\n")).translated); + WalletLogPrintf("%s\n", Join(warnings, Untranslated("\n")).original); nWalletBackups = -2; return false; } @@ -5522,7 +5522,7 @@ bool CWallet::AutoBackupWallet(const fs::path& wallet_path, bilingual_str& error if (fs::exists(backupFile)) { warnings.push_back(_("Failed to create backup, file already exists! This could happen if you restarted wallet in less than 60 seconds. You can continue if you are ok with this.")); - WalletLogPrintf("%s\n", Join(warnings, Untranslated("\n")).translated); + WalletLogPrintf("%s\n", Join(warnings, Untranslated("\n")).original); return false; } if(fs::exists(sourceFile)) { @@ -5531,7 +5531,7 @@ bool CWallet::AutoBackupWallet(const fs::path& wallet_path, bilingual_str& error WalletLogPrintf("Creating backup of %s -> %s\n", sourceFile.string(), backupFile.string()); } catch(fs::filesystem_error &error) { warnings.push_back(strprintf(_("Failed to create backup, error: %s"), fsbridge::get_filesystem_error_message(error))); - WalletLogPrintf("%s\n", Join(warnings, Untranslated("\n")).translated); + WalletLogPrintf("%s\n", Join(warnings, Untranslated("\n")).original); nWalletBackups = -1; return false; } @@ -5570,7 +5570,7 @@ bool CWallet::AutoBackupWallet(const fs::path& wallet_path, bilingual_str& error WalletLogPrintf("Old backup deleted: %s\n", file.second); } catch(fs::filesystem_error &error) { warnings.push_back(strprintf(_("Failed to delete backup, error: %s"), fsbridge::get_filesystem_error_message(error))); - WalletLogPrintf("%s\n", Join(warnings, Untranslated("\n")).translated); + WalletLogPrintf("%s\n", Join(warnings, Untranslated("\n")).original); return false; } }