feat: Full UI internationalization, pool hashrate stats, and layout caching
- Replace all hardcoded English strings with TR() translation keys across every tab, dialog, and component (~20 UI files) - Expand all 8 language files (de, es, fr, ja, ko, pt, ru, zh) with complete translations (~37k lines added) - Improve i18n loader with exe-relative path fallback and English base fallback for missing keys - Add pool-side hashrate polling via pool stats API in xmrig_manager - Introduce Layout::beginFrame() per-frame caching and refresh balance layout config only on schema generation change - Offload daemon output parsing to worker thread - Add CJK subset fallback font for Chinese/Japanese/Korean glyphs
This commit is contained in:
@@ -72,31 +72,31 @@ void ExportTransactionsDialog::render(App* app)
|
||||
auto exportBtn = S.button("dialogs.export-transactions", "export-button");
|
||||
auto closeBtn = S.button("dialogs.export-transactions", "close-button");
|
||||
|
||||
if (material::BeginOverlayDialog("Export Transactions to CSV", &s_open, win.width, 0.94f)) {
|
||||
if (material::BeginOverlayDialog(TR("export_tx_title"), &s_open, win.width, 0.94f)) {
|
||||
const auto& state = app->getWalletState();
|
||||
|
||||
ImGui::Text("Export %zu transactions to CSV file.", state.transactions.size());
|
||||
ImGui::Text(TR("export_tx_count"), state.transactions.size());
|
||||
|
||||
ImGui::Spacing();
|
||||
ImGui::Separator();
|
||||
ImGui::Spacing();
|
||||
|
||||
// Filename
|
||||
ImGui::Text("Output filename:");
|
||||
ImGui::Text("%s", TR("output_filename"));
|
||||
ImGui::SetNextItemWidth(-1);
|
||||
ImGui::InputText("##Filename", s_filename, sizeof(s_filename));
|
||||
|
||||
ImGui::Spacing();
|
||||
ImGui::TextDisabled("File will be saved in: ~/.config/ObsidianDragon/");
|
||||
ImGui::TextDisabled("%s", TR("file_save_location"));
|
||||
|
||||
ImGui::Spacing();
|
||||
ImGui::Separator();
|
||||
ImGui::Spacing();
|
||||
|
||||
// Export button
|
||||
if (material::StyledButton("Export", ImVec2(exportBtn.width, 0), S.resolveFont(exportBtn.font))) {
|
||||
if (material::StyledButton(TR("export"), ImVec2(exportBtn.width, 0), S.resolveFont(exportBtn.font))) {
|
||||
if (state.transactions.empty()) {
|
||||
Notifications::instance().warning("No transactions to export");
|
||||
Notifications::instance().warning(TR("export_tx_none"));
|
||||
} else {
|
||||
std::string configDir = util::Platform::getConfigDir();
|
||||
std::string filepath = configDir + "/" + s_filename;
|
||||
@@ -104,7 +104,7 @@ void ExportTransactionsDialog::render(App* app)
|
||||
std::ofstream file(filepath);
|
||||
if (!file.is_open()) {
|
||||
s_status = "Failed to create file";
|
||||
Notifications::instance().error("Failed to create CSV file");
|
||||
Notifications::instance().error(TR("export_tx_file_fail"));
|
||||
} else {
|
||||
// Write CSV header
|
||||
file << "Date,Type,Amount,Address,TXID,Confirmations,Memo\n";
|
||||
@@ -142,7 +142,7 @@ void ExportTransactionsDialog::render(App* app)
|
||||
|
||||
s_status = "Exported " + std::to_string(state.transactions.size()) +
|
||||
" transactions to: " + filepath;
|
||||
Notifications::instance().success("Transactions exported successfully");
|
||||
Notifications::instance().success(TR("export_tx_success"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user