fix: sidebar nav text overflow for long translations

- Add text scaling for section labels (TOOLS, ADVANCED) in sidebar
- Separate explorer_section key from explorer nav label to fix ALL CAPS
- Shorten long sidebar translations: es/pt settings, pt overview, ru tools/advanced
- Fix explorer translations from ALL CAPS to proper case in all languages
This commit is contained in:
2026-04-12 18:45:48 -05:00
parent 40cec14ebf
commit aa26ab5fbd
24 changed files with 22297 additions and 20583 deletions

View File

@@ -1450,27 +1450,27 @@ void App::renderStatusBar()
ImGui::SameLine(0, sbIconTextGap);
// Show truncated warmup status (e.g. "Activating best chain... (Block 12345)")
const char* warmupText = state_.warmup_status.empty()
? "Warming up..." : state_.warmup_status.c_str();
? TR("sb_warming_up") : state_.warmup_status.c_str();
ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.0f, 1.0f), "%s", warmupText);
} else if (state_.connected) {
ImGui::PushFont(ui::material::Type().iconSmall());
ImGui::TextColored(ImVec4(0.2f, 0.8f, 0.2f, dotOpacity), ICON_MD_CIRCLE);
ImGui::PopFont();
ImGui::SameLine(0, sbIconTextGap);
ImGui::Text("Connected");
ImGui::Text("%s", TR("connected"));
} else {
ImGui::PushFont(ui::material::Type().iconSmall());
ImGui::TextColored(ImVec4(0.8f, 0.2f, 0.2f, dotOpacity), ICON_MD_CIRCLE);
ImGui::PopFont();
ImGui::SameLine(0, sbIconTextGap);
ImGui::Text("Disconnected");
ImGui::Text("%s", TR("disconnected"));
}
// Block height
ImGui::SameLine(0, sbSectionGap);
ImGui::TextDisabled("|");
ImGui::SameLine(0, sbSeparatorGap);
ImGui::Text("Block: %d", state_.sync.blocks);
ImGui::Text(TR("sb_block"), state_.sync.blocks);
// Sync status or peer count
ImGui::SameLine(0, sbSectionGap);
@@ -1480,13 +1480,13 @@ void App::renderStatusBar()
// Show rescan progress (takes priority over sync)
// Use animated dots if progress is unknown (0%)
if (state_.sync.rescan_progress > 0.01f) {
ImGui::TextColored(ImVec4(0.6f, 0.8f, 1.0f, 1.0f), "Rescanning %.0f%%",
ImGui::TextColored(ImVec4(0.6f, 0.8f, 1.0f, 1.0f), TR("sb_rescanning_pct"),
state_.sync.rescan_progress * 100.0f);
} else {
// Animated "Rescanning..." with pulsing dots
int dots = (int)(ImGui::GetTime() * 2.0f) % 4;
const char* dotStr = (dots == 0) ? "." : (dots == 1) ? ".." : (dots == 2) ? "..." : "";
ImGui::TextColored(ImVec4(0.6f, 0.8f, 1.0f, 1.0f), "Rescanning%s", dotStr);
ImGui::TextColored(ImVec4(0.6f, 0.8f, 1.0f, 1.0f), "%s%s", TR("sb_rescanning"), dotStr);
}
} else if (state_.sync.syncing) {
int chainTip = state_.longestchain > 0 ? state_.longestchain : state_.sync.headers;
@@ -1528,14 +1528,14 @@ void App::renderStatusBar()
snprintf(eta, sizeof(eta), "%dm %ds", eta_sec / 60, eta_sec % 60);
else
snprintf(eta, sizeof(eta), "%ds", eta_sec);
ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.0f, 1.0f), "Syncing %.1f%% (%d left, %.0f blk/s, ~%s)",
ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.0f, 1.0f), TR("sb_syncing_eta"),
state_.sync.verification_progress * 100.0, blocksLeft, s_blocks_per_sec, eta);
} else {
ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.0f, 1.0f), "Syncing %.1f%% (%d left)",
ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.0f, 1.0f), TR("sb_syncing_basic"),
state_.sync.verification_progress * 100.0, blocksLeft);
}
} else if (state_.connected) {
ImGui::Text("Peers: %zu", state_.peers.size());
ImGui::Text(TR("sb_peers"), state_.peers.size());
}
// Network hashrate (if connected and have data)
@@ -1544,13 +1544,13 @@ void App::renderStatusBar()
ImGui::TextDisabled("|");
ImGui::SameLine(0, sbSeparatorGap);
if (state_.mining.networkHashrate >= 1e9) {
ImGui::Text("Net: %.2f GH/s", state_.mining.networkHashrate / 1e9);
ImGui::Text(TR("sb_net_ghs"), state_.mining.networkHashrate / 1e9);
} else if (state_.mining.networkHashrate >= 1e6) {
ImGui::Text("Net: %.2f MH/s", state_.mining.networkHashrate / 1e6);
ImGui::Text(TR("sb_net_mhs"), state_.mining.networkHashrate / 1e6);
} else if (state_.mining.networkHashrate >= 1e3) {
ImGui::Text("Net: %.2f KH/s", state_.mining.networkHashrate / 1e3);
ImGui::Text(TR("sb_net_khs"), state_.mining.networkHashrate / 1e3);
} else {
ImGui::Text("Net: %.1f H/s", state_.mining.networkHashrate);
ImGui::Text(TR("sb_net_hs"), state_.mining.networkHashrate);
}
}
@@ -1567,7 +1567,7 @@ void App::renderStatusBar()
double displayHashrate = state_.pool_mining.xmrig_running
? state_.pool_mining.hashrate_10s
: state_.mining.localHashrate;
ImGui::TextColored(ImVec4(0.3f, 0.8f, 0.3f, 1.0f), "%.1f H/s",
ImGui::TextColored(ImVec4(0.3f, 0.8f, 0.3f, 1.0f), TR("sb_mining_hs"),
displayHashrate);
}
@@ -1583,7 +1583,7 @@ void App::renderStatusBar()
ImGui::SameLine(0, sbIconTextGap);
int dots = (int)(ImGui::GetTime() * 2.0f) % 4;
const char* dotStr = (dots == 0) ? "." : (dots == 1) ? ".." : (dots == 2) ? "..." : "";
ImGui::TextColored(ImVec4(0.6f, 0.8f, 1.0f, 1.0f), "Importing keys%s", dotStr);
ImGui::TextColored(ImVec4(0.6f, 0.8f, 1.0f, 1.0f), "%s%s", TR("sb_importing_keys"), dotStr);
}
// Right side: version always at far right, connection status to its left.
@@ -1605,7 +1605,7 @@ void App::renderStatusBar()
ImGui::SameLine(statusX);
ImGui::TextDisabled("%s", connection_status_.c_str());
} else if (!daemon_status_.empty() && daemon_status_.find("Error") != std::string::npos) {
const char* errText = "Daemon not found";
const char* errText = TR("sb_daemon_not_found");
float statusW = ImGui::CalcTextSize(errText).x;
float statusX = versionX - statusW - gap;
ImGui::SameLine(statusX);
@@ -2062,12 +2062,12 @@ bool App::startEmbeddedDaemon()
// Try to extract embedded resources if available
if (resources::hasEmbeddedResources()) {
DEBUG_LOGF("Extracting embedded Sapling params...\n");
daemon_status_ = "Extracting Sapling parameters...";
daemon_status_ = TR("sb_extracting_sapling");
resources::extractEmbeddedResources();
// Check again after extraction
if (!rpc::Connection::verifySaplingParams()) {
daemon_status_ = "Failed to extract Sapling parameters.";
daemon_status_ = TR("sb_sapling_failed");
DEBUG_LOGF("Sapling params still not found after extraction!\n");
DEBUG_LOGF("Expected location: %s\n", rpc::Connection::getSaplingParamsDir().c_str());
return false;
@@ -2113,7 +2113,7 @@ bool App::startEmbeddedDaemon()
if (copied && rpc::Connection::verifySaplingParams()) {
DEBUG_LOGF("Sapling params copied from exe directory successfully\n");
} else {
daemon_status_ = "Sapling parameters not found. They should be in: " + rpc::Connection::getSaplingParamsDir();
daemon_status_ = TR("sb_sapling_not_found");
DEBUG_LOGF("Sapling params not found and no embedded resources available!\n");
DEBUG_LOGF("Expected location: %s\n", rpc::Connection::getSaplingParamsDir().c_str());
return false;
@@ -2163,16 +2163,16 @@ bool App::startEmbeddedDaemon()
embedded_daemon_->setStateCallback([this](daemon::EmbeddedDaemon::State state, const std::string& msg) {
switch (state) {
case daemon::EmbeddedDaemon::State::Starting:
daemon_status_ = "Starting dragonxd...";
daemon_status_ = TR("sb_starting_daemon");
break;
case daemon::EmbeddedDaemon::State::Running:
daemon_status_ = "dragonxd running";
daemon_status_ = TR("sb_dragonxd_running");
break;
case daemon::EmbeddedDaemon::State::Stopping:
daemon_status_ = "Stopping dragonxd...";
daemon_status_ = TR("sb_dragonxd_stopping");
break;
case daemon::EmbeddedDaemon::State::Stopped:
daemon_status_ = "dragonxd stopped";
daemon_status_ = TR("sb_dragonxd_stopped");
break;
case daemon::EmbeddedDaemon::State::Error:
daemon_status_ = "Error: " + msg;
@@ -3105,7 +3105,7 @@ void App::restartDaemon()
}
DEBUG_LOGF("[App] Restarting embedded daemon...\n");
connection_status_ = "Restarting daemon...";
connection_status_ = TR("sb_restarting_daemon");
// Disconnect RPC so the loading overlay appears
if (rpc_ && rpc_->isConnected()) {