diff --git a/doc/translation_strings_policy.md b/doc/translation_strings_policy.md index b13ce3c47b..45216cb254 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 ddeed9b66a..b4f9529a80 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 551077f7d8..ba0d26eac4 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 1c63c33fd5..610ab29524 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 970cc8798c..8ff841082b 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 3559e51a8f..8127286c5d 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 09bfc08016..a20584e2d1 100644 --- a/src/interfaces/chain.cpp +++ b/src/interfaces/chain.cpp @@ -345,7 +345,7 @@ public: 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 a0a54124ea..946c69ff86 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 @@ public: 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 c7b3ad96df..e818f3fb66 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 @@ public: 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 5658a02749..1cb96f358e 100644 --- a/src/interfaces/node.h +++ b/src/interfaces/node.h @@ -294,11 +294,11 @@ public: //! 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 33804a8cb9..dd1e55e54d 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 1e95b61ef1..daa5dfa200 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 @@ private: 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 2de1758530..c994bc1d8e 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 174074e753..0c48a1c728 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 5f2ee4b320..671edf833d 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 84252271da..bcd8897516 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 095206700c..02754f469a 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 99a061c458..10014e672f 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 e0afe235d3..8c26201aa3 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 @@ public: 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 @@ public: }; /** 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 01b1f6166f..b4f8fd9f38 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 81e0e2e3dc..f897c6c203 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 27b5ca2304..0dcd5d9143 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 61fd68e19f..0c915d2ce1 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; } }