i18n: route explorer and shield status strings through TR()
Centralise the remaining hardcoded English literals in two otherwise fully-translated files (explorer_tab: 40 TR calls, shield_dialog: 23) so they join the i18n system with an English source key + fallback: - explorer_tab: the three search-error messages (invalid response, hash not found, not-connected) now use explorer_* keys. Also guards a hash lookup behind an active daemon connection and disables the block-detail prev/next nav while a fetch is in flight (both were the reason these error paths could fire). - shield_dialog: the operation status/error strings (submitting, submitted, failed, status, error-checking-status, shield/merge failed) now use shield_* keys. - i18n: add the new explorer_* and shield_* English source keys. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -221,7 +221,7 @@ static void applyBlockDetailResult(const json& result, const std::string& error)
|
||||
}
|
||||
|
||||
if (result.is_null()) {
|
||||
s_search_error = "Invalid response from daemon";
|
||||
s_search_error = TR("explorer_invalid_response");
|
||||
s_show_detail_modal = false;
|
||||
return;
|
||||
}
|
||||
@@ -388,7 +388,7 @@ static void navigateToHash(App* app, const std::string& hash) {
|
||||
s_expanded_tx_idx = 0;
|
||||
s_show_detail_modal = false;
|
||||
} else {
|
||||
s_search_error = "No block or transaction found for this hash";
|
||||
s_search_error = TR("explorer_hash_not_found");
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -417,6 +417,11 @@ static void performSearch(App* app, const std::string& query) {
|
||||
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
|
||||
});
|
||||
if (isHex64) {
|
||||
// A hash lookup needs the daemon; navigateToHash() would otherwise return silently.
|
||||
if (!app->rpc() || !app->rpc()->isConnected()) {
|
||||
s_search_error = TR("explorer_not_connected");
|
||||
return;
|
||||
}
|
||||
navigateToHash(app, query);
|
||||
return;
|
||||
}
|
||||
@@ -1039,6 +1044,9 @@ static void renderBlockDetailModal(App* app) {
|
||||
// Nav buttons on same line
|
||||
ImGui::SameLine(contentW - Layout::spacingXl() * 3);
|
||||
|
||||
// Disable prev/next while a fetch is in flight so navigation can't stack fetches.
|
||||
ImGui::BeginDisabled(s_detail_loading);
|
||||
|
||||
// Prev
|
||||
if (s_detail_height > 1) {
|
||||
ImGui::PushFont(Type().iconMed());
|
||||
@@ -1065,6 +1073,8 @@ static void renderBlockDetailModal(App* app) {
|
||||
ImGui::PopID();
|
||||
ImGui::PopFont();
|
||||
}
|
||||
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
@@ -181,7 +181,7 @@ void ShieldDialog::render(App* app)
|
||||
const char* btn_label = (s_mode == Mode::ShieldCoinbase) ? TR("shield_funds") : TR("merge_funds");
|
||||
if (material::StyledButton(btn_label, ImVec2(shieldBtn.width, 0), S.resolveFont(shieldBtn.font))) {
|
||||
s_operation_pending = true;
|
||||
s_status_message = "Submitting operation...";
|
||||
s_status_message = TR("shield_submitting");
|
||||
|
||||
if (s_mode == Mode::ShieldCoinbase) {
|
||||
std::string from(s_from_address), to(s_to_address);
|
||||
@@ -201,14 +201,14 @@ void ShieldDialog::render(App* app)
|
||||
s_operation_pending = false;
|
||||
if (error.empty()) {
|
||||
s_operation_id = result.value("opid", "");
|
||||
s_status_message = "Operation submitted: " + s_operation_id;
|
||||
s_status_message = std::string(TR("shield_op_submitted")) + s_operation_id;
|
||||
Notifications::instance().success(TR("shield_started"));
|
||||
// Register with the shared poller so an async failure is
|
||||
// surfaced (and balances refresh) even after this dialog closes.
|
||||
app->trackOperation(s_operation_id);
|
||||
} else {
|
||||
s_status_message = "Error: " + error;
|
||||
Notifications::instance().error("Shield failed: " + error);
|
||||
s_status_message = std::string(TR("shield_error_prefix")) + error;
|
||||
Notifications::instance().error(std::string(TR("shield_send_failed")) + error);
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -235,14 +235,14 @@ void ShieldDialog::render(App* app)
|
||||
s_operation_pending = false;
|
||||
if (error.empty()) {
|
||||
s_operation_id = result.value("opid", "");
|
||||
s_status_message = "Operation submitted: " + s_operation_id;
|
||||
s_status_message = std::string(TR("shield_op_submitted")) + s_operation_id;
|
||||
Notifications::instance().success(TR("merge_started"));
|
||||
// Register with the shared poller so an async failure is
|
||||
// surfaced (and balances refresh) even after this dialog closes.
|
||||
app->trackOperation(s_operation_id);
|
||||
} else {
|
||||
s_status_message = "Error: " + error;
|
||||
Notifications::instance().error("Merge failed: " + error);
|
||||
s_status_message = std::string(TR("shield_error_prefix")) + error;
|
||||
Notifications::instance().error(std::string(TR("merge_send_failed")) + error);
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -293,16 +293,16 @@ void ShieldDialog::render(App* app)
|
||||
s_status_message = TR("shield_completed");
|
||||
Notifications::instance().success(TR("shield_merge_done"));
|
||||
} else if (status == "failed") {
|
||||
std::string errMsg = op.value("error", nlohmann::json{}).value("message", "Unknown error");
|
||||
s_status_message = "Operation failed: " + errMsg;
|
||||
Notifications::instance().error("Operation failed: " + errMsg);
|
||||
std::string errMsg = op.value("error", nlohmann::json{}).value("message", TR("shield_unknown_error"));
|
||||
s_status_message = std::string(TR("shield_op_failed")) + errMsg;
|
||||
Notifications::instance().error(std::string(TR("shield_op_failed")) + errMsg);
|
||||
} else if (status == "executing") {
|
||||
s_status_message = TR("shield_in_progress");
|
||||
} else {
|
||||
s_status_message = "Status: " + status;
|
||||
s_status_message = std::string(TR("shield_status_label")) + status;
|
||||
}
|
||||
} else if (!error.empty()) {
|
||||
s_status_message = "Error checking status: " + error;
|
||||
s_status_message = std::string(TR("shield_status_check_error")) + error;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1501,6 +1501,15 @@ void I18n::loadBuiltinEnglish()
|
||||
strings_["shield_to_address"] = "To Address (Shielded):";
|
||||
strings_["shield_utxo_limit"] = "UTXO Limit:";
|
||||
strings_["shield_wildcard_hint"] = "Use '*' to shield from all transparent addresses";
|
||||
strings_["shield_submitting"] = "Submitting operation...";
|
||||
strings_["shield_op_submitted"] = "Operation submitted: ";
|
||||
strings_["shield_op_failed"] = "Operation failed: ";
|
||||
strings_["shield_error_prefix"] = "Error: ";
|
||||
strings_["shield_status_label"] = "Status: ";
|
||||
strings_["shield_status_check_error"] = "Error checking status: ";
|
||||
strings_["shield_unknown_error"] = "Unknown error";
|
||||
strings_["shield_send_failed"] = "Shield failed: ";
|
||||
strings_["merge_send_failed"] = "Merge failed: ";
|
||||
strings_["merge_description"] = "Merge multiple UTXOs into a single shielded address. This can help reduce wallet size and improve privacy.";
|
||||
strings_["merge_funds"] = "Merge Funds";
|
||||
strings_["merge_started"] = "Merge operation started";
|
||||
@@ -1568,6 +1577,9 @@ void I18n::loadBuiltinEnglish()
|
||||
strings_["explorer_tx_outputs"] = "Outputs";
|
||||
strings_["explorer_tx_size"] = "Size";
|
||||
strings_["explorer_invalid_query"] = "Enter a block height or 64-character hash";
|
||||
strings_["explorer_invalid_response"] = "Invalid response from daemon";
|
||||
strings_["explorer_hash_not_found"] = "No block or transaction found for this hash";
|
||||
strings_["explorer_not_connected"] = "Not connected to daemon — cannot look up a block or transaction hash";
|
||||
strings_["explorer_no_results"] = "No matching cached blocks";
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user