fix: accurate sync speed display, add missing i18n keys, native language names

- Fix blk/s calculation that was inflated ~10x due to resetting the
  time baseline every frame instead of only when blocks advanced
- Add decay when no new blocks arrive for 10s so rate doesn't stay stale
- Add 7 missing translation keys (timeout_off/1min/5min/15min/30min/1hour,
  slider_off) to all 8 language files so settings dropdowns translate
- Show language names in native script (中文, Русский, 日本語, 한국어)
This commit is contained in:
2026-04-12 15:12:36 -05:00
parent d2dccbac05
commit 6e2db50675
20 changed files with 5169 additions and 4910 deletions

View File

@@ -654,6 +654,7 @@
"show_qr_code": "QR-Code anzeigen", "show_qr_code": "QR-Code anzeigen",
"showing_transactions": "Zeige %d%d von %d Transaktionen (gesamt: %zu)", "showing_transactions": "Zeige %d%d von %d Transaktionen (gesamt: %zu)",
"simple_background": "Einfacher Hintergrund", "simple_background": "Einfacher Hintergrund",
"slider_off": "Aus",
"start_mining": "Mining starten", "start_mining": "Mining starten",
"status": "Status", "status": "Status",
"stop_external": "Externen Daemon stoppen", "stop_external": "Externen Daemon stoppen",
@@ -670,6 +671,12 @@
"time_hours_ago": "vor %d Stunden", "time_hours_ago": "vor %d Stunden",
"time_minutes_ago": "vor %d Minuten", "time_minutes_ago": "vor %d Minuten",
"time_seconds_ago": "vor %d Sekunden", "time_seconds_ago": "vor %d Sekunden",
"timeout_15min": "15 Min",
"timeout_1hour": "1 Stunde",
"timeout_1min": "1 Min",
"timeout_30min": "30 Min",
"timeout_5min": "5 Min",
"timeout_off": "Aus",
"to": "An", "to": "An",
"to_upper": "AN", "to_upper": "AN",
"tools": "WERKZEUGE", "tools": "WERKZEUGE",

View File

@@ -654,6 +654,7 @@
"show_qr_code": "Mostrar Código QR", "show_qr_code": "Mostrar Código QR",
"showing_transactions": "Mostrando %d%d de %d transacciones (total: %zu)", "showing_transactions": "Mostrando %d%d de %d transacciones (total: %zu)",
"simple_background": "Fondo simple", "simple_background": "Fondo simple",
"slider_off": "Apagado",
"start_mining": "Iniciar Minería", "start_mining": "Iniciar Minería",
"status": "Estado", "status": "Estado",
"stop_external": "Detener daemon externo", "stop_external": "Detener daemon externo",
@@ -670,6 +671,12 @@
"time_hours_ago": "hace %d horas", "time_hours_ago": "hace %d horas",
"time_minutes_ago": "hace %d minutos", "time_minutes_ago": "hace %d minutos",
"time_seconds_ago": "hace %d segundos", "time_seconds_ago": "hace %d segundos",
"timeout_15min": "15 min",
"timeout_1hour": "1 hora",
"timeout_1min": "1 min",
"timeout_30min": "30 min",
"timeout_5min": "5 min",
"timeout_off": "Apagado",
"to": "Para", "to": "Para",
"to_upper": "PARA", "to_upper": "PARA",
"tools": "HERRAMIENTAS", "tools": "HERRAMIENTAS",

View File

@@ -654,6 +654,7 @@
"show_qr_code": "Afficher le code QR", "show_qr_code": "Afficher le code QR",
"showing_transactions": "Affichage %d%d sur %d transactions (total : %zu)", "showing_transactions": "Affichage %d%d sur %d transactions (total : %zu)",
"simple_background": "Arrière-plan simple", "simple_background": "Arrière-plan simple",
"slider_off": "Désactivé",
"start_mining": "Démarrer le minage", "start_mining": "Démarrer le minage",
"status": "Statut", "status": "Statut",
"stop_external": "Arrêter le daemon externe", "stop_external": "Arrêter le daemon externe",
@@ -670,6 +671,12 @@
"time_hours_ago": "il y a %d heures", "time_hours_ago": "il y a %d heures",
"time_minutes_ago": "il y a %d minutes", "time_minutes_ago": "il y a %d minutes",
"time_seconds_ago": "il y a %d secondes", "time_seconds_ago": "il y a %d secondes",
"timeout_15min": "15 min",
"timeout_1hour": "1 heure",
"timeout_1min": "1 min",
"timeout_30min": "30 min",
"timeout_5min": "5 min",
"timeout_off": "Désactivé",
"to": "À", "to": "À",
"to_upper": "À", "to_upper": "À",
"tools": "OUTILS", "tools": "OUTILS",

View File

@@ -654,6 +654,7 @@
"show_qr_code": "QRコードを表示", "show_qr_code": "QRコードを表示",
"showing_transactions": "%d%d / %d 件の取引を表示中(合計:%zu", "showing_transactions": "%d%d / %d 件の取引を表示中(合計:%zu",
"simple_background": "シンプル背景", "simple_background": "シンプル背景",
"slider_off": "オフ",
"start_mining": "マイニング開始", "start_mining": "マイニング開始",
"status": "ステータス", "status": "ステータス",
"stop_external": "外部デーモンを停止", "stop_external": "外部デーモンを停止",
@@ -670,6 +671,12 @@
"time_hours_ago": "%d時間前", "time_hours_ago": "%d時間前",
"time_minutes_ago": "%d分前", "time_minutes_ago": "%d分前",
"time_seconds_ago": "%d秒前", "time_seconds_ago": "%d秒前",
"timeout_15min": "15分",
"timeout_1hour": "1時間",
"timeout_1min": "1分",
"timeout_30min": "30分",
"timeout_5min": "5分",
"timeout_off": "オフ",
"to": "宛先", "to": "宛先",
"to_upper": "宛先", "to_upper": "宛先",
"tools": "ツール", "tools": "ツール",

View File

@@ -654,6 +654,7 @@
"show_qr_code": "QR 코드 표시", "show_qr_code": "QR 코드 표시",
"showing_transactions": "%d%d / %d건의 거래 표시 중 (총: %zu)", "showing_transactions": "%d%d / %d건의 거래 표시 중 (총: %zu)",
"simple_background": "단순 배경", "simple_background": "단순 배경",
"slider_off": "끔",
"start_mining": "채굴 시작", "start_mining": "채굴 시작",
"status": "상태", "status": "상태",
"stop_external": "외부 데몬 중지", "stop_external": "외부 데몬 중지",
@@ -670,6 +671,12 @@
"time_hours_ago": "%d시간 전", "time_hours_ago": "%d시간 전",
"time_minutes_ago": "%d분 전", "time_minutes_ago": "%d분 전",
"time_seconds_ago": "%d초 전", "time_seconds_ago": "%d초 전",
"timeout_15min": "15분",
"timeout_1hour": "1시간",
"timeout_1min": "1분",
"timeout_30min": "30분",
"timeout_5min": "5분",
"timeout_off": "끔",
"to": "받는 곳", "to": "받는 곳",
"to_upper": "받는 곳", "to_upper": "받는 곳",
"tools": "도구", "tools": "도구",

View File

@@ -654,6 +654,7 @@
"show_qr_code": "Mostrar Código QR", "show_qr_code": "Mostrar Código QR",
"showing_transactions": "Mostrando %d%d de %d transações (total: %zu)", "showing_transactions": "Mostrando %d%d de %d transações (total: %zu)",
"simple_background": "Fundo simples", "simple_background": "Fundo simples",
"slider_off": "Desligado",
"start_mining": "Iniciar Mineração", "start_mining": "Iniciar Mineração",
"status": "Status", "status": "Status",
"stop_external": "Parar daemon externo", "stop_external": "Parar daemon externo",
@@ -670,6 +671,12 @@
"time_hours_ago": "há %d horas", "time_hours_ago": "há %d horas",
"time_minutes_ago": "há %d minutos", "time_minutes_ago": "há %d minutos",
"time_seconds_ago": "há %d segundos", "time_seconds_ago": "há %d segundos",
"timeout_15min": "15 min",
"timeout_1hour": "1 hora",
"timeout_1min": "1 min",
"timeout_30min": "30 min",
"timeout_5min": "5 min",
"timeout_off": "Desligado",
"to": "Para", "to": "Para",
"to_upper": "PARA", "to_upper": "PARA",
"tools": "FERRAMENTAS", "tools": "FERRAMENTAS",

View File

@@ -654,6 +654,7 @@
"show_qr_code": "Показать QR-код", "show_qr_code": "Показать QR-код",
"showing_transactions": "Показано %d%d из %d транзакций (всего: %zu)", "showing_transactions": "Показано %d%d из %d транзакций (всего: %zu)",
"simple_background": "Простой фон", "simple_background": "Простой фон",
"slider_off": "Выкл",
"start_mining": "Начать майнинг", "start_mining": "Начать майнинг",
"status": "Статус", "status": "Статус",
"stop_external": "Остановить внешний daemon", "stop_external": "Остановить внешний daemon",
@@ -670,6 +671,12 @@
"time_hours_ago": "%d часов назад", "time_hours_ago": "%d часов назад",
"time_minutes_ago": "%d минут назад", "time_minutes_ago": "%d минут назад",
"time_seconds_ago": "%d секунд назад", "time_seconds_ago": "%d секунд назад",
"timeout_15min": "15 мин",
"timeout_1hour": "1 час",
"timeout_1min": "1 мин",
"timeout_30min": "30 мин",
"timeout_5min": "5 мин",
"timeout_off": "Выкл",
"to": "Кому", "to": "Кому",
"to_upper": "КОМУ", "to_upper": "КОМУ",
"tools": "ИНСТРУМЕНТЫ", "tools": "ИНСТРУМЕНТЫ",

View File

@@ -654,6 +654,7 @@
"show_qr_code": "显示二维码", "show_qr_code": "显示二维码",
"showing_transactions": "显示第 %d%d 笔,共 %d 笔交易(总计:%zu", "showing_transactions": "显示第 %d%d 笔,共 %d 笔交易(总计:%zu",
"simple_background": "简单背景", "simple_background": "简单背景",
"slider_off": "关闭",
"start_mining": "开始挖矿", "start_mining": "开始挖矿",
"status": "状态", "status": "状态",
"stop_external": "停止外部守护进程", "stop_external": "停止外部守护进程",
@@ -670,6 +671,12 @@
"time_hours_ago": "%d 小时前", "time_hours_ago": "%d 小时前",
"time_minutes_ago": "%d 分钟前", "time_minutes_ago": "%d 分钟前",
"time_seconds_ago": "%d 秒前", "time_seconds_ago": "%d 秒前",
"timeout_15min": "15分钟",
"timeout_1hour": "1小时",
"timeout_1min": "1分钟",
"timeout_30min": "30分钟",
"timeout_5min": "5分钟",
"timeout_off": "关闭",
"to": "至", "to": "至",
"to_upper": "至", "to_upper": "至",
"tools": "工具", "tools": "工具",

View File

@@ -1081,15 +1081,16 @@ void App::render()
int fgVtxStart = fgDL->VtxBuffer.Size; int fgVtxStart = fgDL->VtxBuffer.Size;
// --------------------------------------------------------------- // ---------------------------------------------------------------
// Loading overlay — show only while daemon is not yet connected. // Loading overlay — show only on tabs that truly need wallet data.
// Once connected, all tabs render normally; individual tabs show // Tabs that work without full daemon connection:
// inline sync-progress indicators when the chain is still syncing. // Console, Peers, Settings, Market, Mining
// Pages that remain accessible even without a connection: // Tabs that need balance/transaction data (show overlay):
// Console, Peers, Settings // Overview, Send, Receive, History
// --------------------------------------------------------------- // ---------------------------------------------------------------
bool pageNeedsDaemon = (current_page_ != ui::NavPage::Console && bool pageNeedsWalletData = (current_page_ == ui::NavPage::Overview ||
current_page_ != ui::NavPage::Peers && current_page_ == ui::NavPage::Send ||
current_page_ != ui::NavPage::Settings); current_page_ == ui::NavPage::Receive ||
current_page_ == ui::NavPage::History);
bool daemonReady = state_.connected && !state_.warming_up; bool daemonReady = state_.connected && !state_.warming_up;
// Don't show lock screen while pool mining — xmrig runs independently // Don't show lock screen while pool mining — xmrig runs independently
@@ -1098,12 +1099,12 @@ void App::render()
if (state_.isLocked() && !poolMiningActive) { if (state_.isLocked() && !poolMiningActive) {
// Lock screen — covers tab content just like the loading overlay // Lock screen — covers tab content just like the loading overlay
renderLockScreen(); renderLockScreen();
} else if (state_.warming_up) { } else if (pageNeedsWalletData && state_.warming_up) {
// Daemon is reachable but still initializing — show warmup overlay // Daemon is reachable but still initializing — show warmup overlay
// without blocking on encryption state (getwalletinfo fails during warmup) // only on wallet-data tabs. Other tabs render normally.
lock_screen_was_visible_ = false; lock_screen_was_visible_ = false;
renderLoadingOverlay(contentH); renderLoadingOverlay(contentH);
} else if (pageNeedsDaemon && (!daemonReady || (state_.connected && !state_.encryption_state_known))) { } else if (pageNeedsWalletData && (!daemonReady || (state_.connected && !state_.encryption_state_known))) {
// Track how long we've been waiting for encryption state // Track how long we've been waiting for encryption state
if (state_.connected && !state_.encryption_state_known) { if (state_.connected && !state_.encryption_state_known) {
encryption_check_timer_ += ImGui::GetIO().DeltaTime; encryption_check_timer_ += ImGui::GetIO().DeltaTime;
@@ -1484,7 +1485,11 @@ void App::renderStatusBar()
static double s_prev_time = 0.0; static double s_prev_time = 0.0;
static double s_blocks_per_sec = 0.0; static double s_blocks_per_sec = 0.0;
double now = ImGui::GetTime(); double now = ImGui::GetTime();
if (s_prev_time > 0.0 && state_.sync.blocks > s_prev_blocks) { if (s_prev_time == 0.0) {
// First sample — seed baseline, don't compute rate yet
s_prev_blocks = state_.sync.blocks;
s_prev_time = now;
} else if (state_.sync.blocks > s_prev_blocks) {
double dt = now - s_prev_time; double dt = now - s_prev_time;
if (dt > 0.5) { if (dt > 0.5) {
double raw = (state_.sync.blocks - s_prev_blocks) / dt; double raw = (state_.sync.blocks - s_prev_blocks) / dt;
@@ -1495,9 +1500,10 @@ void App::renderStatusBar()
s_prev_blocks = state_.sync.blocks; s_prev_blocks = state_.sync.blocks;
s_prev_time = now; s_prev_time = now;
} }
} else { } else if (now - s_prev_time > 10.0) {
s_prev_blocks = state_.sync.blocks; // No new blocks for 10s — decay the displayed rate
s_prev_time = now; s_blocks_per_sec *= 0.5;
s_prev_time = now;
} }
if (s_blocks_per_sec > 0.1) { if (s_blocks_per_sec > 0.1) {
@@ -2786,6 +2792,21 @@ void App::renderLoadingOverlay(float contentH)
curY += ts.y + gap; curY += ts.y + gap;
} }
// -------------------------------------------------------------------
// 2b. Warmup description (subtitle explaining what's happening)
// -------------------------------------------------------------------
if (state_.warming_up && !state_.warmup_description.empty()) {
const char* descText = state_.warmup_description.c_str();
ImFont* capFont = Type().caption();
if (!capFont) capFont = ImGui::GetFont();
// Wrap to barW so long descriptions don't overflow
ImVec2 ts = capFont->CalcTextSizeA(capFont->LegacySize, FLT_MAX, barW, descText);
dl->AddText(capFont, capFont->LegacySize,
ImVec2(wp.x + cx - ts.x * 0.5f, curY),
IM_COL32(160, 160, 160, 200), descText, nullptr, barW);
curY += ts.y + gap;
}
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// 3. Sync progress bar (if connected and syncing) // 3. Sync progress bar (if connected and syncing)
// ------------------------------------------------------------------- // -------------------------------------------------------------------

View File

@@ -49,6 +49,40 @@ namespace dragonx {
using json = nlohmann::json; using json = nlohmann::json;
// ============================================================================
// Warmup Message Translation
// Maps raw daemon RPC warmup messages to user-friendly text.
// ============================================================================
struct WarmupText {
const char* title;
const char* description;
};
static WarmupText translateWarmup(const std::string& raw)
{
if (raw.find("Loading") != std::string::npos)
return {"Loading blockchain data...",
"Reading the block database from disk. This may take a few minutes after updates."};
if (raw.find("Verifying") != std::string::npos)
return {"Verifying blockchain...",
"Checking recent blocks to make sure your chain data is valid."};
if (raw.find("Activating") != std::string::npos)
return {"Processing blocks...",
"Applying blocks to build the current chain state."};
if (raw.find("Rewinding") != std::string::npos)
return {"Reorganizing chain...",
"A chain reorganization was detected. Reverting to the correct chain."};
if (raw.find("Rescanning") != std::string::npos)
return {"Scanning for transactions...",
"Searching the blockchain for transactions belonging to your wallet. This can take a while."};
if (raw.find("Pruning") != std::string::npos)
return {"Optimizing storage...",
"Removing old block data to free up disk space."};
// Fallback: use the raw message
return {raw.c_str(), ""};
}
// ============================================================================ // ============================================================================
// Connection Management // Connection Management
// ============================================================================ // ============================================================================
@@ -164,7 +198,9 @@ void App::tryConnect()
// fail until warmup completes. Set the warmup state so // fail until warmup completes. Set the warmup state so
// the UI shows status instead of a blocking overlay. // the UI shows status instead of a blocking overlay.
state_.warming_up = true; state_.warming_up = true;
state_.warmup_status = warmupStatus; auto wt = translateWarmup(warmupStatus);
state_.warmup_status = wt.title;
state_.warmup_description = wt.description;
// Append current block height from daemon output // Append current block height from daemon output
if (embedded_daemon_) { if (embedded_daemon_) {
int h = embedded_daemon_->getLastBlockHeight(); int h = embedded_daemon_->getLastBlockHeight();
@@ -560,6 +596,7 @@ void App::refreshCoreData()
// Warmup finished — daemon is fully ready // Warmup finished — daemon is fully ready
state_.warming_up = false; state_.warming_up = false;
state_.warmup_status.clear(); state_.warmup_status.clear();
state_.warmup_description.clear();
connection_status_ = "Connected"; connection_status_ = "Connected";
VERBOSE_LOGF("[warmup] Daemon ready, warmup complete\n"); VERBOSE_LOGF("[warmup] Daemon ready, warmup complete\n");
// Parse initial info // Parse initial info
@@ -577,7 +614,9 @@ void App::refreshCoreData()
refreshData(); refreshData();
} else { } else {
// Still warming up — update status // Still warming up — update status
state_.warmup_status = errMsg; auto wt = translateWarmup(errMsg);
state_.warmup_status = wt.title;
state_.warmup_description = wt.description;
if (embedded_daemon_) { if (embedded_daemon_) {
int h = embedded_daemon_->getLastBlockHeight(); int h = embedded_daemon_->getLastBlockHeight();
if (h > 0) if (h > 0)

View File

@@ -181,7 +181,8 @@ struct WalletState {
// Connection // Connection
bool connected = false; bool connected = false;
bool warming_up = false; // daemon reachable but in RPC warmup (error -28) bool warming_up = false; // daemon reachable but in RPC warmup (error -28)
std::string warmup_status; // e.g. "Activating best chain..." std::string warmup_status; // user-friendly title, e.g. "Processing blocks..."
std::string warmup_description; // subtitle explaining the stage
int daemon_version = 0; int daemon_version = 0;
std::string daemon_subversion; std::string daemon_subversion;
int protocol_version = 0; int protocol_version = 0;
@@ -254,6 +255,7 @@ struct WalletState {
connected = false; connected = false;
warming_up = false; warming_up = false;
warmup_status.clear(); warmup_status.clear();
warmup_description.clear();
daemon_version = 0; daemon_version = 0;
daemon_subversion.clear(); daemon_subversion.clear();
protocol_version = 0; protocol_version = 0;

View File

@@ -2736,56 +2736,73 @@ unsigned char res_lang_de_json[] = {
0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x3a, 0x20, 0x22, 0x45, 0x69, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x3a, 0x20, 0x22, 0x45, 0x69,
0x6e, 0x66, 0x61, 0x63, 0x68, 0x65, 0x72, 0x20, 0x48, 0x69, 0x6e, 0x74, 0x6e, 0x66, 0x61, 0x63, 0x68, 0x65, 0x72, 0x20, 0x48, 0x69, 0x6e, 0x74,
0x65, 0x72, 0x67, 0x72, 0x75, 0x6e, 0x64, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x65, 0x72, 0x67, 0x72, 0x75, 0x6e, 0x64, 0x22, 0x2c, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x22, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x20, 0x20, 0x22, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x6f, 0x66,
0x69, 0x6e, 0x67, 0x22, 0x3a, 0x20, 0x22, 0x4d, 0x69, 0x6e, 0x69, 0x6e, 0x66, 0x22, 0x3a, 0x20, 0x22, 0x41, 0x75, 0x73, 0x22, 0x2c, 0x0a, 0x20,
0x67, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x6e, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x22, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x6d, 0x69,
0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22,
0x3a, 0x20, 0x22, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x2c, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x74, 0x6f, 0x70, 0x5f, 0x65, 0x78,
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x22, 0x3a, 0x20, 0x22, 0x45, 0x78,
0x74, 0x65, 0x72, 0x6e, 0x65, 0x6e, 0x20, 0x44, 0x61, 0x65, 0x6d, 0x6f,
0x6e, 0x20, 0x73, 0x74, 0x6f, 0x70, 0x70, 0x65, 0x6e, 0x22, 0x2c, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x74, 0x6f, 0x70, 0x5f, 0x6d, 0x69,
0x6e, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x20, 0x22, 0x4d, 0x69, 0x6e, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x20, 0x22, 0x4d, 0x69, 0x6e, 0x69,
0x6e, 0x67, 0x20, 0x73, 0x74, 0x6f, 0x70, 0x70, 0x65, 0x6e, 0x22, 0x2c, 0x6e, 0x67, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x6e, 0x22, 0x2c,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
0x74, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x22, 0x3a, 0x20, 0x22, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x2c,
0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x20, 0x22, 0x54, 0x72, 0x61, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x74, 0x6f, 0x70, 0x5f, 0x65,
0x73, 0x61, 0x6b, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x69, 0x72, 0x64, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x22, 0x3a, 0x20, 0x22, 0x45,
0x20, 0xc3, 0xbc, 0x62, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x6c, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x6e, 0x20, 0x44, 0x61, 0x65, 0x6d,
0x74, 0x2e, 0x2e, 0x2e, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6f, 0x6e, 0x20, 0x73, 0x74, 0x6f, 0x70, 0x70, 0x65, 0x6e, 0x22, 0x2c,
0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x3a, 0x20, 0x22, 0x45, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x74, 0x6f, 0x70, 0x5f, 0x6d,
0x72, 0x66, 0x6f, 0x6c, 0x67, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x20, 0x22, 0x4d, 0x69, 0x6e,
0x22, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x22, 0x3a, 0x20, 0x22, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x74, 0x6f, 0x70, 0x70, 0x65, 0x6e, 0x22,
0x5a, 0x75, 0x73, 0x61, 0x6d, 0x6d, 0x65, 0x6e, 0x66, 0x61, 0x73, 0x73, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x75, 0x62, 0x6d, 0x69,
0x75, 0x6e, 0x67, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x73, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61,
0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x20, 0x22, 0x53, 0x79, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x20, 0x22, 0x54, 0x72, 0x61,
0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x73, 0x69, 0x65, 0x72, 0x65, 0x6e, 0x73, 0x61, 0x6b, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x69, 0x72,
0x2e, 0x2e, 0x2e, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x64, 0x20, 0xc3, 0xbc, 0x62, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x74, 0x65,
0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x22, 0x3a, 0x6c, 0x74, 0x2e, 0x2e, 0x2e, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x20, 0x22, 0x54, 0x2d, 0x41, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x6e, 0x22, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x3a, 0x20, 0x22,
0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x65, 0x73, 0x74, 0x45, 0x72, 0x66, 0x6f, 0x6c, 0x67, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20,
0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x20, 0x22, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x22, 0x3a, 0x20,
0x3a, 0x20, 0x22, 0x54, 0x65, 0x73, 0x74, 0x65, 0x6e, 0x22, 0x2c, 0x0a, 0x22, 0x5a, 0x75, 0x73, 0x61, 0x6d, 0x6d, 0x65, 0x6e, 0x66, 0x61, 0x73,
0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x68, 0x65, 0x6d, 0x65, 0x22, 0x3a, 0x73, 0x75, 0x6e, 0x67, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22,
0x20, 0x22, 0x44, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x22, 0x2c, 0x0a, 0x20, 0x73, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x20, 0x22, 0x53,
0x20, 0x20, 0x20, 0x22, 0x74, 0x68, 0x65, 0x6d, 0x65, 0x5f, 0x65, 0x66, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x73, 0x69, 0x65, 0x72,
0x66, 0x65, 0x63, 0x74, 0x73, 0x22, 0x3a, 0x20, 0x22, 0x44, 0x65, 0x73, 0x65, 0x2e, 0x2e, 0x2e, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22,
0x69, 0x67, 0x6e, 0x2d, 0x45, 0x66, 0x66, 0x65, 0x6b, 0x74, 0x65, 0x22, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x22,
0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x3a, 0x20, 0x22, 0x54, 0x2d, 0x41, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65,
0x64, 0x61, 0x79, 0x73, 0x5f, 0x61, 0x67, 0x6f, 0x22, 0x3a, 0x20, 0x22, 0x6e, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x65, 0x73,
0x76, 0x6f, 0x72, 0x20, 0x25, 0x64, 0x20, 0x54, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x22, 0x3a, 0x20, 0x22, 0x54, 0x65, 0x73, 0x74, 0x65, 0x6e, 0x22, 0x2c,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x68, 0x65, 0x6d, 0x65, 0x22,
0x3a, 0x20, 0x22, 0x44, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x22, 0x2c, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x68, 0x65, 0x6d, 0x65, 0x5f, 0x65,
0x66, 0x66, 0x65, 0x63, 0x74, 0x73, 0x22, 0x3a, 0x20, 0x22, 0x44, 0x65,
0x73, 0x69, 0x67, 0x6e, 0x2d, 0x45, 0x66, 0x66, 0x65, 0x6b, 0x74, 0x65,
0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x69, 0x6d, 0x65,
0x5f, 0x68, 0x6f, 0x75, 0x72, 0x73, 0x5f, 0x61, 0x67, 0x6f, 0x22, 0x3a, 0x5f, 0x64, 0x61, 0x79, 0x73, 0x5f, 0x61, 0x67, 0x6f, 0x22, 0x3a, 0x20,
0x20, 0x22, 0x76, 0x6f, 0x72, 0x20, 0x25, 0x64, 0x20, 0x53, 0x74, 0x75, 0x22, 0x76, 0x6f, 0x72, 0x20, 0x25, 0x64, 0x20, 0x54, 0x61, 0x67, 0x65,
0x6e, 0x64, 0x65, 0x6e, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x6e, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x69, 0x6d,
0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x75, 0x74, 0x65, 0x73, 0x65, 0x5f, 0x68, 0x6f, 0x75, 0x72, 0x73, 0x5f, 0x61, 0x67, 0x6f, 0x22,
0x5f, 0x61, 0x67, 0x6f, 0x22, 0x3a, 0x20, 0x22, 0x76, 0x6f, 0x72, 0x20, 0x3a, 0x20, 0x22, 0x76, 0x6f, 0x72, 0x20, 0x25, 0x64, 0x20, 0x53, 0x74,
0x25, 0x64, 0x20, 0x4d, 0x69, 0x6e, 0x75, 0x74, 0x65, 0x6e, 0x22, 0x2c,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x73,
0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x5f, 0x61, 0x67, 0x6f, 0x22, 0x3a,
0x20, 0x22, 0x76, 0x6f, 0x72, 0x20, 0x25, 0x64, 0x20, 0x53, 0x65, 0x6b,
0x75, 0x6e, 0x64, 0x65, 0x6e, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x6e, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x22, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x75, 0x74, 0x65,
0x73, 0x5f, 0x61, 0x67, 0x6f, 0x22, 0x3a, 0x20, 0x22, 0x76, 0x6f, 0x72,
0x20, 0x25, 0x64, 0x20, 0x4d, 0x69, 0x6e, 0x75, 0x74, 0x65, 0x6e, 0x22,
0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x69, 0x6d, 0x65, 0x5f,
0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x5f, 0x61, 0x67, 0x6f, 0x22,
0x3a, 0x20, 0x22, 0x76, 0x6f, 0x72, 0x20, 0x25, 0x64, 0x20, 0x53, 0x65,
0x6b, 0x75, 0x6e, 0x64, 0x65, 0x6e, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x22, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x31, 0x35,
0x6d, 0x69, 0x6e, 0x22, 0x3a, 0x20, 0x22, 0x31, 0x35, 0x20, 0x4d, 0x69,
0x6e, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x69, 0x6d,
0x65, 0x6f, 0x75, 0x74, 0x5f, 0x31, 0x68, 0x6f, 0x75, 0x72, 0x22, 0x3a,
0x20, 0x22, 0x31, 0x20, 0x53, 0x74, 0x75, 0x6e, 0x64, 0x65, 0x22, 0x2c,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75,
0x74, 0x5f, 0x31, 0x6d, 0x69, 0x6e, 0x22, 0x3a, 0x20, 0x22, 0x31, 0x20,
0x4d, 0x69, 0x6e, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74,
0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x33, 0x30, 0x6d, 0x69, 0x6e,
0x22, 0x3a, 0x20, 0x22, 0x33, 0x30, 0x20, 0x4d, 0x69, 0x6e, 0x22, 0x2c,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75,
0x74, 0x5f, 0x35, 0x6d, 0x69, 0x6e, 0x22, 0x3a, 0x20, 0x22, 0x35, 0x20,
0x4d, 0x69, 0x6e, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74,
0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x6f, 0x66, 0x66, 0x22, 0x3a,
0x20, 0x22, 0x41, 0x75, 0x73, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x22, 0x74, 0x6f, 0x22, 0x3a, 0x20, 0x22, 0x41, 0x6e, 0x22, 0x2c, 0x0a, 0x22, 0x74, 0x6f, 0x22, 0x3a, 0x20, 0x22, 0x41, 0x6e, 0x22, 0x2c, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x6f, 0x5f, 0x75, 0x70, 0x70, 0x65, 0x20, 0x20, 0x20, 0x20, 0x22, 0x74, 0x6f, 0x5f, 0x75, 0x70, 0x70, 0x65,
0x72, 0x22, 0x3a, 0x20, 0x22, 0x41, 0x4e, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x72, 0x22, 0x3a, 0x20, 0x22, 0x41, 0x4e, 0x22, 0x2c, 0x0a, 0x20, 0x20,
@@ -3402,4 +3419,4 @@ unsigned char res_lang_de_json[] = {
0x73, 0x65, 0x73, 0x22, 0x3a, 0x20, 0x22, 0x5a, 0x2d, 0x41, 0x64, 0x72, 0x73, 0x65, 0x73, 0x22, 0x3a, 0x20, 0x22, 0x5a, 0x2d, 0x41, 0x64, 0x72,
0x65, 0x73, 0x73, 0x65, 0x6e, 0x22, 0x0a, 0x7d, 0x0a 0x65, 0x73, 0x73, 0x65, 0x6e, 0x22, 0x0a, 0x7d, 0x0a
}; };
unsigned int res_lang_de_json_len = 40821; unsigned int res_lang_de_json_len = 41025;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -33,13 +33,13 @@ I18n::I18n()
// Cyrillic glyphs are included in the Ubuntu font glyph ranges. // Cyrillic glyphs are included in the Ubuntu font glyph ranges.
registerLanguage("en", "English"); registerLanguage("en", "English");
registerLanguage("es", "Español"); registerLanguage("es", "Español");
registerLanguage("zh", "Chinese"); registerLanguage("zh", "中文");
registerLanguage("ru", "Russian"); registerLanguage("ru", "Русский");
registerLanguage("de", "Deutsch"); registerLanguage("de", "Deutsch");
registerLanguage("fr", "Français"); registerLanguage("fr", "Français");
registerLanguage("pt", "Português"); registerLanguage("pt", "Português");
registerLanguage("ja", "Japanese"); registerLanguage("ja", "日本語");
registerLanguage("ko", "Korean"); registerLanguage("ko", "한국어");
// Load default English strings (built-in fallback) // Load default English strings (built-in fallback)
loadLanguage("en"); loadLanguage("en");