i18n(wizard): translate the first-run wizard (was all hardcoded English)
The first-run wizard predated the i18n system — every label, button, and help line was hardcoded English. Route them all through TR(): - 62 literals in app_wizard.cpp replaced with TR(). Where a wizard string is a parallel of existing content, it reuses the existing key (the whole bootstrap_* family, plus theme / language / balance_layout / low_spec_mode / ui_opacity / console_scanline / download / retry / cancel) so it inherits their translations and stays consistent with Settings. Button labels drop their ##id suffix and use TR(key) directly (the app's established TactileButton(TR(...)) pattern; the wizard's phase buttons never share a frame, so no id collision). - 55 new wiz_* English keys in i18n.cpp for the wizard-specific strings, and their translations back-filled across all 8 languages (es/de/fr/pt/ru/zh/ja/ko); format specifiers (%s, %zu) and newlines preserved. CJK subset rebuilt. Verified on the sweep: English renders with correct labels in place (all keys resolve), and a German run shows the reused + new keys translated end-to-end (Darstellung / Acryl-Glaseffekte / Verschlüsseln & Weiter …). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Binary file not shown.
@@ -1369,6 +1369,61 @@
|
||||
"warning_upper": "WARNUNG!",
|
||||
"website": "Webseite",
|
||||
"window_opacity": "Fenster-Transparenz",
|
||||
"wiz_acrylic": "Acryl-Glaseffekte",
|
||||
"wiz_acrylic_desc": "Transparente Unschärfe auf Panels (Aus deaktiviert)",
|
||||
"wiz_already_encrypted": "Wallet ist bereits verschlüsselt",
|
||||
"wiz_already_encrypted_desc": "Ihr Wallet ist mit einer Passphrase geschützt. Es sind keine weiteren Schritte erforderlich.",
|
||||
"wiz_appearance": "Darstellung",
|
||||
"wiz_bootstrap": "Bootstrap",
|
||||
"wiz_bootstrap_desc": "Laden Sie ein Blockchain-Bootstrap herunter, um die anfängliche Synchronisierung erheblich zu beschleunigen.\n\nIhre vorhandene wallet.dat wird NICHT verändert oder ersetzt.",
|
||||
"wiz_bootstrap_failed": "Bootstrap fehlgeschlagen",
|
||||
"wiz_confirm": "Bestätigen:",
|
||||
"wiz_continue": "Weiter",
|
||||
"wiz_daemon_sending_stop": "Stopp-Befehl wird gesendet...",
|
||||
"wiz_daemon_stop_failed": "Daemon wurde nicht gestoppt — manuell versuchen.",
|
||||
"wiz_daemon_stopped_ok": "Daemon gestoppt.",
|
||||
"wiz_daemon_waiting_stop": "Warten, bis der Daemon herunterfährt...",
|
||||
"wiz_download_failed": "Download fehlgeschlagen",
|
||||
"wiz_encrypt_bg": "Die Verschlüsselung wird im Hintergrund abgeschlossen",
|
||||
"wiz_encrypt_continue": "Verschlüsseln & Weiter",
|
||||
"wiz_encrypt_desc": "Verschlüsseln Sie Ihr Wallet, um private Schlüssel mit einer Passphrase zu schützen.",
|
||||
"wiz_encrypt_warning": "Wenn Sie Ihre Passphrase verlieren, verlieren Sie den Zugriff auf Ihr Guthaben.",
|
||||
"wiz_encryption": "Verschlüsselung",
|
||||
"wiz_ext_daemon_running": "Externer Daemon läuft",
|
||||
"wiz_ext_daemon_warning": "Er muss gestoppt werden, bevor ein Bootstrap heruntergeladen wird, sonst könnten Chain-Daten beschädigt werden.",
|
||||
"wiz_level": "Stufe:",
|
||||
"wiz_lowspec_desc": "Alle aufwendigen visuellen Effekte deaktivieren",
|
||||
"wiz_off": "Aus",
|
||||
"wiz_pass_mismatch": "Passphrasen stimmen nicht überein",
|
||||
"wiz_pass_spaces": "Passphrase hat führende/nachfolgende Leerzeichen — entfernen Sie diese",
|
||||
"wiz_pass_too_short": "Passphrase muss mindestens 8 Zeichen lang sein (%zu/8)",
|
||||
"wiz_passphrase": "Passphrase:",
|
||||
"wiz_pin_confirm": "PIN bestätigen:",
|
||||
"wiz_pin_invalid": "PIN muss 4-8 Ziffern haben",
|
||||
"wiz_pin_label": "PIN (4-8 Ziffern):",
|
||||
"wiz_pin_mismatch": "PINs stimmen nicht überein",
|
||||
"wiz_pin_optional": "Schnellentsperr-PIN (optional)",
|
||||
"wiz_pin_title": "Schnellentsperr-PIN",
|
||||
"wiz_scanline_desc": "CRT-Scanline-Effekt in der Konsole",
|
||||
"wiz_skip": "Überspringen",
|
||||
"wiz_skip_confirm": "OHNE Verschlüsselung fortfahren? Schlüssel werden unverschlüsselt gespeichert — klicken Sie erneut auf Überspringen, um zu bestätigen.",
|
||||
"wiz_step1": "Schritt 1",
|
||||
"wiz_step2": "Schritt 2",
|
||||
"wiz_step3": "Schritt 3",
|
||||
"wiz_stop_daemon": "Daemon stoppen",
|
||||
"wiz_strength": "Stärke: %s",
|
||||
"wiz_strength_fair": "Mäßig",
|
||||
"wiz_strength_good": "Gut",
|
||||
"wiz_strength_strong": "Stark",
|
||||
"wiz_strength_weak": "Schwach",
|
||||
"wiz_theme_builtin": "Integriert",
|
||||
"wiz_theme_custom": "Benutzerdefiniert",
|
||||
"wiz_theme_effects": "Visuelle Theme-Effekte",
|
||||
"wiz_theme_effects_desc": "Animierte Ränder, Farbverlauf",
|
||||
"wiz_theme_invalid": " (ungültig)",
|
||||
"wiz_ui_opacity_desc": "Transparenz von Karten & Seitenleiste (1.0 = deckend)",
|
||||
"wiz_welcome_sub": "Ein paar schnelle Einstellungen und Ihr Full Node ist bereit.",
|
||||
"wiz_welcome_title": "Willkommen bei ObsidianDragon!",
|
||||
"wizard_daemon_start_failed": "Daemon-Start fehlgeschlagen — wird automatisch wiederholt",
|
||||
"xmrig_browse_releases": "Alle Releases durchsuchen…",
|
||||
"xmrig_checking": "Nach dem neuesten Miner wird gesucht…",
|
||||
|
||||
@@ -1369,6 +1369,61 @@
|
||||
"warning_upper": "¡ADVERTENCIA!",
|
||||
"website": "Sitio Web",
|
||||
"window_opacity": "Opacidad de ventana",
|
||||
"wiz_acrylic": "Efectos de vidrio acrílico",
|
||||
"wiz_acrylic_desc": "Desenfoque translúcido en paneles (Desactivado lo apaga)",
|
||||
"wiz_already_encrypted": "La cartera ya está cifrada",
|
||||
"wiz_already_encrypted_desc": "Tu cartera está protegida con una frase de contraseña. No es necesaria ninguna acción adicional.",
|
||||
"wiz_appearance": "Apariencia",
|
||||
"wiz_bootstrap": "Bootstrap",
|
||||
"wiz_bootstrap_desc": "Descarga un bootstrap de la cadena de bloques para acelerar drásticamente la sincronización inicial.\\n\\nTu wallet.dat existente NO se modificará ni se reemplazará.",
|
||||
"wiz_bootstrap_failed": "Error en el bootstrap",
|
||||
"wiz_confirm": "Confirmar:",
|
||||
"wiz_continue": "Continuar",
|
||||
"wiz_daemon_sending_stop": "Enviando comando de detención...",
|
||||
"wiz_daemon_stop_failed": "El daemon no se detuvo — inténtalo manualmente.",
|
||||
"wiz_daemon_stopped_ok": "Daemon detenido.",
|
||||
"wiz_daemon_waiting_stop": "Esperando a que el daemon se cierre...",
|
||||
"wiz_download_failed": "Error de descarga",
|
||||
"wiz_encrypt_bg": "El cifrado se completará en segundo plano",
|
||||
"wiz_encrypt_continue": "Cifrar y continuar",
|
||||
"wiz_encrypt_desc": "Cifra tu cartera para proteger las claves privadas con una frase de contraseña.",
|
||||
"wiz_encrypt_warning": "Si pierdes tu frase de contraseña, pierdes el acceso a tus fondos.",
|
||||
"wiz_encryption": "Cifrado",
|
||||
"wiz_ext_daemon_running": "Daemon externo en ejecución",
|
||||
"wiz_ext_daemon_warning": "Debe detenerse antes de descargar un bootstrap; de lo contrario, los datos de la cadena podrían corromperse.",
|
||||
"wiz_level": "Nivel:",
|
||||
"wiz_lowspec_desc": "Desactivar todos los efectos visuales pesados",
|
||||
"wiz_off": "Desactivado",
|
||||
"wiz_pass_mismatch": "Las frases de contraseña no coinciden",
|
||||
"wiz_pass_spaces": "La frase de contraseña tiene espacios al inicio o al final — elimínalos",
|
||||
"wiz_pass_too_short": "La frase de contraseña debe tener al menos 8 caracteres (%zu/8)",
|
||||
"wiz_passphrase": "Frase de contraseña:",
|
||||
"wiz_pin_confirm": "Confirmar PIN:",
|
||||
"wiz_pin_invalid": "El PIN debe tener entre 4 y 8 dígitos",
|
||||
"wiz_pin_label": "PIN (4-8 dígitos):",
|
||||
"wiz_pin_mismatch": "Los PIN no coinciden",
|
||||
"wiz_pin_optional": "PIN de desbloqueo rápido (opcional)",
|
||||
"wiz_pin_title": "PIN de desbloqueo rápido",
|
||||
"wiz_scanline_desc": "Efecto de líneas de barrido CRT en la consola",
|
||||
"wiz_skip": "Omitir",
|
||||
"wiz_skip_confirm": "¿Continuar SIN cifrado? Las claves se almacenarán sin cifrar — haz clic en Omitir de nuevo para confirmar.",
|
||||
"wiz_step1": "Paso 1",
|
||||
"wiz_step2": "Paso 2",
|
||||
"wiz_step3": "Paso 3",
|
||||
"wiz_stop_daemon": "Detener daemon",
|
||||
"wiz_strength": "Seguridad: %s",
|
||||
"wiz_strength_fair": "Aceptable",
|
||||
"wiz_strength_good": "Buena",
|
||||
"wiz_strength_strong": "Fuerte",
|
||||
"wiz_strength_weak": "Débil",
|
||||
"wiz_theme_builtin": "Integrado",
|
||||
"wiz_theme_custom": "Personalizado",
|
||||
"wiz_theme_effects": "Efectos visuales del tema",
|
||||
"wiz_theme_effects_desc": "Bordes animados, capa de color",
|
||||
"wiz_theme_invalid": " (no válido)",
|
||||
"wiz_ui_opacity_desc": "Transparencia de tarjetas y barra lateral (1.0 = sólido)",
|
||||
"wiz_welcome_sub": "Unas cuantas opciones rápidas y tu nodo completo estará listo.",
|
||||
"wiz_welcome_title": "¡Bienvenido a ObsidianDragon!",
|
||||
"wizard_daemon_start_failed": "Error al iniciar el daemon — se reintentará automáticamente",
|
||||
"xmrig_browse_releases": "Ver todos los lanzamientos…",
|
||||
"xmrig_checking": "Buscando el minero más reciente…",
|
||||
|
||||
@@ -1369,6 +1369,61 @@
|
||||
"warning_upper": "ATTENTION !",
|
||||
"website": "Site web",
|
||||
"window_opacity": "Opacité de la fenêtre",
|
||||
"wiz_acrylic": "Effets de verre acrylique",
|
||||
"wiz_acrylic_desc": "Flou translucide sur les panneaux (Désactivé les coupe)",
|
||||
"wiz_already_encrypted": "Le portefeuille est déjà chiffré",
|
||||
"wiz_already_encrypted_desc": "Votre portefeuille est protégé par une phrase secrète. Aucune autre action n'est nécessaire.",
|
||||
"wiz_appearance": "Apparence",
|
||||
"wiz_bootstrap": "Amorçage",
|
||||
"wiz_bootstrap_desc": "Téléchargez un amorçage de la blockchain pour accélérer considérablement la synchronisation initiale.\n\nVotre fichier wallet.dat existant NE sera PAS modifié ni remplacé.",
|
||||
"wiz_bootstrap_failed": "Échec de l'amorçage",
|
||||
"wiz_confirm": "Confirmer :",
|
||||
"wiz_continue": "Continuer",
|
||||
"wiz_daemon_sending_stop": "Envoi de la commande d'arrêt...",
|
||||
"wiz_daemon_stop_failed": "Le démon ne s'est pas arrêté — essayez manuellement.",
|
||||
"wiz_daemon_stopped_ok": "Démon arrêté.",
|
||||
"wiz_daemon_waiting_stop": "En attente de l'arrêt du démon...",
|
||||
"wiz_download_failed": "Échec du téléchargement",
|
||||
"wiz_encrypt_bg": "Le chiffrement se terminera en arrière-plan",
|
||||
"wiz_encrypt_continue": "Chiffrer et continuer",
|
||||
"wiz_encrypt_desc": "Chiffrez votre portefeuille pour protéger les clés privées avec une phrase secrète.",
|
||||
"wiz_encrypt_warning": "Si vous perdez votre phrase secrète, vous perdez l'accès à vos fonds.",
|
||||
"wiz_encryption": "Chiffrement",
|
||||
"wiz_ext_daemon_running": "Démon externe en cours d'exécution",
|
||||
"wiz_ext_daemon_warning": "Il doit être arrêté avant de télécharger un amorçage, sinon les données de la chaîne pourraient être corrompues.",
|
||||
"wiz_level": "Niveau :",
|
||||
"wiz_lowspec_desc": "Désactiver tous les effets visuels lourds",
|
||||
"wiz_off": "Désactivé",
|
||||
"wiz_pass_mismatch": "Les phrases secrètes ne correspondent pas",
|
||||
"wiz_pass_spaces": "La phrase secrète comporte des espaces en début/fin — supprimez-les",
|
||||
"wiz_pass_too_short": "La phrase secrète doit comporter au moins 8 caractères (%zu/8)",
|
||||
"wiz_passphrase": "Phrase secrète :",
|
||||
"wiz_pin_confirm": "Confirmer le PIN :",
|
||||
"wiz_pin_invalid": "Le PIN doit comporter 4 à 8 chiffres",
|
||||
"wiz_pin_label": "PIN (4 à 8 chiffres) :",
|
||||
"wiz_pin_mismatch": "Les PIN ne correspondent pas",
|
||||
"wiz_pin_optional": "PIN de déverrouillage rapide (facultatif)",
|
||||
"wiz_pin_title": "PIN de déverrouillage rapide",
|
||||
"wiz_scanline_desc": "Effet de lignes de balayage CRT dans la console",
|
||||
"wiz_skip": "Ignorer",
|
||||
"wiz_skip_confirm": "Continuer SANS chiffrement ? Les clés seront stockées non chiffrées — cliquez à nouveau sur Ignorer pour confirmer.",
|
||||
"wiz_step1": "Étape 1",
|
||||
"wiz_step2": "Étape 2",
|
||||
"wiz_step3": "Étape 3",
|
||||
"wiz_stop_daemon": "Arrêter le démon",
|
||||
"wiz_strength": "Robustesse : %s",
|
||||
"wiz_strength_fair": "Moyenne",
|
||||
"wiz_strength_good": "Bonne",
|
||||
"wiz_strength_strong": "Forte",
|
||||
"wiz_strength_weak": "Faible",
|
||||
"wiz_theme_builtin": "Intégré",
|
||||
"wiz_theme_custom": "Personnalisé",
|
||||
"wiz_theme_effects": "Effets visuels du thème",
|
||||
"wiz_theme_effects_desc": "Bordures animées, voile de couleur",
|
||||
"wiz_theme_invalid": " (non valide)",
|
||||
"wiz_ui_opacity_desc": "Transparence des cartes et de la barre latérale (1.0 = opaque)",
|
||||
"wiz_welcome_sub": "Quelques choix rapides et votre nœud complet est prêt.",
|
||||
"wiz_welcome_title": "Bienvenue dans ObsidianDragon !",
|
||||
"wizard_daemon_start_failed": "Échec du démarrage du daemon — sera réessayé automatiquement",
|
||||
"xmrig_browse_releases": "Parcourir toutes les versions…",
|
||||
"xmrig_checking": "Recherche du dernier mineur…",
|
||||
|
||||
@@ -1369,6 +1369,61 @@
|
||||
"warning_upper": "警告!",
|
||||
"website": "ウェブサイト",
|
||||
"window_opacity": "ウィンドウ透明度",
|
||||
"wiz_acrylic": "アクリルガラス効果",
|
||||
"wiz_acrylic_desc": "パネルの半透明ぼかし(オフで無効化)",
|
||||
"wiz_already_encrypted": "ウォレットはすでに暗号化されています",
|
||||
"wiz_already_encrypted_desc": "ウォレットはパスフレーズで保護されています。これ以上の操作は不要です。",
|
||||
"wiz_appearance": "外観",
|
||||
"wiz_bootstrap": "ブートストラップ",
|
||||
"wiz_bootstrap_desc": "ブロックチェーンのブートストラップをダウンロードして初回同期を大幅に高速化します。\\n\\n既存の wallet.dat は変更も置き換えもされません。",
|
||||
"wiz_bootstrap_failed": "ブートストラップに失敗しました",
|
||||
"wiz_confirm": "確認:",
|
||||
"wiz_continue": "続行",
|
||||
"wiz_daemon_sending_stop": "停止コマンドを送信中...",
|
||||
"wiz_daemon_stop_failed": "デーモンが停止しませんでした — 手動でお試しください。",
|
||||
"wiz_daemon_stopped_ok": "デーモンを停止しました。",
|
||||
"wiz_daemon_waiting_stop": "デーモンの終了を待機中...",
|
||||
"wiz_download_failed": "ダウンロードに失敗しました",
|
||||
"wiz_encrypt_bg": "暗号化はバックグラウンドで完了します",
|
||||
"wiz_encrypt_continue": "暗号化して続行",
|
||||
"wiz_encrypt_desc": "ウォレットを暗号化して、パスフレーズで秘密鍵を保護します。",
|
||||
"wiz_encrypt_warning": "パスフレーズを紛失すると、資金にアクセスできなくなります。",
|
||||
"wiz_encryption": "暗号化",
|
||||
"wiz_ext_daemon_running": "外部デーモンが実行中です",
|
||||
"wiz_ext_daemon_warning": "ブートストラップをダウンロードする前に停止する必要があります。停止しないとチェーンデータが破損する可能性があります。",
|
||||
"wiz_level": "レベル:",
|
||||
"wiz_lowspec_desc": "重い視覚効果をすべて無効にする",
|
||||
"wiz_off": "オフ",
|
||||
"wiz_pass_mismatch": "パスフレーズが一致しません",
|
||||
"wiz_pass_spaces": "パスフレーズの先頭または末尾に空白があります — 削除してください",
|
||||
"wiz_pass_too_short": "パスフレーズは 8 文字以上にしてください(%zu/8)",
|
||||
"wiz_passphrase": "パスフレーズ:",
|
||||
"wiz_pin_confirm": "PIN の確認:",
|
||||
"wiz_pin_invalid": "PIN は 4〜8 桁にしてください",
|
||||
"wiz_pin_label": "PIN(4〜8 桁):",
|
||||
"wiz_pin_mismatch": "PIN が一致しません",
|
||||
"wiz_pin_optional": "クイックロック解除 PIN(任意)",
|
||||
"wiz_pin_title": "クイックロック解除 PIN",
|
||||
"wiz_scanline_desc": "コンソールの CRT 走査線効果",
|
||||
"wiz_skip": "スキップ",
|
||||
"wiz_skip_confirm": "暗号化せずに続行しますか? 鍵は暗号化されずに保存されます — もう一度スキップをクリックして確認してください。",
|
||||
"wiz_step1": "ステップ 1",
|
||||
"wiz_step2": "ステップ 2",
|
||||
"wiz_step3": "ステップ 3",
|
||||
"wiz_stop_daemon": "デーモンを停止",
|
||||
"wiz_strength": "強度:%s",
|
||||
"wiz_strength_fair": "まずまず",
|
||||
"wiz_strength_good": "良い",
|
||||
"wiz_strength_strong": "強い",
|
||||
"wiz_strength_weak": "弱い",
|
||||
"wiz_theme_builtin": "内蔵",
|
||||
"wiz_theme_custom": "カスタム",
|
||||
"wiz_theme_effects": "テーマの視覚効果",
|
||||
"wiz_theme_effects_desc": "枠のアニメーション、カラーウォッシュ",
|
||||
"wiz_theme_invalid": " (無効)",
|
||||
"wiz_ui_opacity_desc": "カードとサイドバーの透明度(1.0 = 不透明)",
|
||||
"wiz_welcome_sub": "いくつか選ぶだけでフルノードの準備が整います。",
|
||||
"wiz_welcome_title": "ObsidianDragon へようこそ!",
|
||||
"wizard_daemon_start_failed": "デーモンの起動に失敗しました — 自動的に再試行されます",
|
||||
"xmrig_browse_releases": "すべてのリリースを表示…",
|
||||
"xmrig_checking": "最新のマイナーを確認中…",
|
||||
|
||||
@@ -1369,6 +1369,61 @@
|
||||
"warning_upper": "경고!",
|
||||
"website": "웹사이트",
|
||||
"window_opacity": "창 투명도",
|
||||
"wiz_acrylic": "아크릴 유리 효과",
|
||||
"wiz_acrylic_desc": "패널에 반투명 블러 적용 (끄면 비활성화)",
|
||||
"wiz_already_encrypted": "지갑이 이미 암호화되어 있습니다",
|
||||
"wiz_already_encrypted_desc": "지갑이 암호로 보호되어 있습니다. 추가 작업이 필요하지 않습니다.",
|
||||
"wiz_appearance": "모양",
|
||||
"wiz_bootstrap": "부트스트랩",
|
||||
"wiz_bootstrap_desc": "블록체인 부트스트랩을 다운로드하여 초기 동기화 속도를 크게 높입니다.\\n\\n기존 wallet.dat은 수정되거나 교체되지 않습니다.",
|
||||
"wiz_bootstrap_failed": "부트스트랩 실패",
|
||||
"wiz_confirm": "확인:",
|
||||
"wiz_continue": "계속",
|
||||
"wiz_daemon_sending_stop": "중지 명령 전송 중...",
|
||||
"wiz_daemon_stop_failed": "데몬이 중지되지 않았습니다 — 수동으로 시도하세요.",
|
||||
"wiz_daemon_stopped_ok": "데몬이 중지되었습니다.",
|
||||
"wiz_daemon_waiting_stop": "데몬 종료를 기다리는 중...",
|
||||
"wiz_download_failed": "다운로드 실패",
|
||||
"wiz_encrypt_bg": "암호화는 백그라운드에서 완료됩니다",
|
||||
"wiz_encrypt_continue": "암호화 후 계속",
|
||||
"wiz_encrypt_desc": "지갑을 암호화하여 암호로 개인 키를 보호합니다.",
|
||||
"wiz_encrypt_warning": "암호를 분실하면 자금에 접근할 수 없게 됩니다.",
|
||||
"wiz_encryption": "암호화",
|
||||
"wiz_ext_daemon_running": "외부 데몬 실행 중",
|
||||
"wiz_ext_daemon_warning": "부트스트랩을 다운로드하기 전에 데몬을 중지해야 합니다. 그렇지 않으면 체인 데이터가 손상될 수 있습니다.",
|
||||
"wiz_level": "수준:",
|
||||
"wiz_lowspec_desc": "모든 무거운 시각 효과 끄기",
|
||||
"wiz_off": "끔",
|
||||
"wiz_pass_mismatch": "암호가 일치하지 않습니다",
|
||||
"wiz_pass_spaces": "암호 앞뒤에 공백이 있습니다 — 제거하세요",
|
||||
"wiz_pass_too_short": "암호는 8자 이상이어야 합니다 (%zu/8)",
|
||||
"wiz_passphrase": "암호:",
|
||||
"wiz_pin_confirm": "PIN 확인:",
|
||||
"wiz_pin_invalid": "PIN은 4-8자리여야 합니다",
|
||||
"wiz_pin_label": "PIN (4-8자리):",
|
||||
"wiz_pin_mismatch": "PIN이 일치하지 않습니다",
|
||||
"wiz_pin_optional": "빠른 잠금 해제 PIN (선택 사항)",
|
||||
"wiz_pin_title": "빠른 잠금 해제 PIN",
|
||||
"wiz_scanline_desc": "콘솔의 CRT 스캔라인 효과",
|
||||
"wiz_skip": "건너뛰기",
|
||||
"wiz_skip_confirm": "암호화 없이 계속하시겠습니까? 키가 암호화되지 않은 채로 저장됩니다 — 확인하려면 건너뛰기를 다시 클릭하세요.",
|
||||
"wiz_step1": "1단계",
|
||||
"wiz_step2": "2단계",
|
||||
"wiz_step3": "3단계",
|
||||
"wiz_stop_daemon": "데몬 중지",
|
||||
"wiz_strength": "강도: %s",
|
||||
"wiz_strength_fair": "보통",
|
||||
"wiz_strength_good": "양호",
|
||||
"wiz_strength_strong": "강함",
|
||||
"wiz_strength_weak": "약함",
|
||||
"wiz_theme_builtin": "기본 제공",
|
||||
"wiz_theme_custom": "사용자 지정",
|
||||
"wiz_theme_effects": "테마 시각 효과",
|
||||
"wiz_theme_effects_desc": "애니메이션 테두리, 컬러 워시",
|
||||
"wiz_theme_invalid": " (잘못됨)",
|
||||
"wiz_ui_opacity_desc": "카드 및 사이드바 투명도 (1.0 = 불투명)",
|
||||
"wiz_welcome_sub": "몇 가지만 선택하면 풀 노드가 준비됩니다.",
|
||||
"wiz_welcome_title": "ObsidianDragon에 오신 것을 환영합니다!",
|
||||
"wizard_daemon_start_failed": "데몬 시작 실패 — 자동으로 재시도됩니다",
|
||||
"xmrig_browse_releases": "모든 릴리스 보기…",
|
||||
"xmrig_checking": "최신 채굴기를 확인하는 중…",
|
||||
|
||||
@@ -1369,6 +1369,61 @@
|
||||
"warning_upper": "AVISO!",
|
||||
"website": "Website",
|
||||
"window_opacity": "Opacidade da Janela",
|
||||
"wiz_acrylic": "Efeitos de vidro acrílico",
|
||||
"wiz_acrylic_desc": "Desfoque translúcido nos painéis (Desativado remove)",
|
||||
"wiz_already_encrypted": "A carteira já está encriptada",
|
||||
"wiz_already_encrypted_desc": "A sua carteira está protegida com uma frase-passe. Não é necessária nenhuma ação adicional.",
|
||||
"wiz_appearance": "Aparência",
|
||||
"wiz_bootstrap": "Bootstrap",
|
||||
"wiz_bootstrap_desc": "Baixe um bootstrap da blockchain para acelerar drasticamente a sincronização inicial.\\n\\nO seu wallet.dat existente NÃO será modificado nem substituído.",
|
||||
"wiz_bootstrap_failed": "Falha no bootstrap",
|
||||
"wiz_confirm": "Confirmar:",
|
||||
"wiz_continue": "Continuar",
|
||||
"wiz_daemon_sending_stop": "A enviar comando de parada...",
|
||||
"wiz_daemon_stop_failed": "O daemon não parou — tente manualmente.",
|
||||
"wiz_daemon_stopped_ok": "Daemon parado.",
|
||||
"wiz_daemon_waiting_stop": "A aguardar o encerramento do daemon...",
|
||||
"wiz_download_failed": "Falha no download",
|
||||
"wiz_encrypt_bg": "A encriptação será concluída em segundo plano",
|
||||
"wiz_encrypt_continue": "Encriptar e continuar",
|
||||
"wiz_encrypt_desc": "Encripte a sua carteira para proteger as chaves privadas com uma frase-passe.",
|
||||
"wiz_encrypt_warning": "Se perder a sua frase-passe, perde o acesso aos seus fundos.",
|
||||
"wiz_encryption": "Encriptação",
|
||||
"wiz_ext_daemon_running": "Daemon externo em execução",
|
||||
"wiz_ext_daemon_warning": "Deve ser parado antes de baixar um bootstrap, caso contrário os dados da cadeia podem ficar corrompidos.",
|
||||
"wiz_level": "Nível:",
|
||||
"wiz_lowspec_desc": "Desativar todos os efeitos visuais pesados",
|
||||
"wiz_off": "Desativado",
|
||||
"wiz_pass_mismatch": "As frases-passe não coincidem",
|
||||
"wiz_pass_spaces": "A frase-passe tem espaços no início/fim — remova-os",
|
||||
"wiz_pass_too_short": "A frase-passe deve ter pelo menos 8 caracteres (%zu/8)",
|
||||
"wiz_passphrase": "Frase-passe:",
|
||||
"wiz_pin_confirm": "Confirmar PIN:",
|
||||
"wiz_pin_invalid": "O PIN deve ter 4-8 dígitos",
|
||||
"wiz_pin_label": "PIN (4-8 dígitos):",
|
||||
"wiz_pin_mismatch": "Os PINs não coincidem",
|
||||
"wiz_pin_optional": "PIN de desbloqueio rápido (opcional)",
|
||||
"wiz_pin_title": "PIN de desbloqueio rápido",
|
||||
"wiz_scanline_desc": "Efeito de scanline CRT na consola",
|
||||
"wiz_skip": "Ignorar",
|
||||
"wiz_skip_confirm": "Continuar SEM encriptação? As chaves serão armazenadas sem encriptação — clique em Ignorar novamente para confirmar.",
|
||||
"wiz_step1": "Passo 1",
|
||||
"wiz_step2": "Passo 2",
|
||||
"wiz_step3": "Passo 3",
|
||||
"wiz_stop_daemon": "Parar daemon",
|
||||
"wiz_strength": "Força: %s",
|
||||
"wiz_strength_fair": "Razoável",
|
||||
"wiz_strength_good": "Boa",
|
||||
"wiz_strength_strong": "Forte",
|
||||
"wiz_strength_weak": "Fraca",
|
||||
"wiz_theme_builtin": "Integrado",
|
||||
"wiz_theme_custom": "Personalizado",
|
||||
"wiz_theme_effects": "Efeitos visuais do tema",
|
||||
"wiz_theme_effects_desc": "Bordas animadas, matiz de cor",
|
||||
"wiz_theme_invalid": " (inválido)",
|
||||
"wiz_ui_opacity_desc": "Transparência de cartões e barra lateral (1.0 = sólido)",
|
||||
"wiz_welcome_sub": "Algumas escolhas rápidas e o seu full node estará pronto.",
|
||||
"wiz_welcome_title": "Bem-vindo ao ObsidianDragon!",
|
||||
"wizard_daemon_start_failed": "Falha ao iniciar o daemon — será tentado novamente automaticamente",
|
||||
"xmrig_browse_releases": "Navegar por todos os lançamentos…",
|
||||
"xmrig_checking": "Verificando o minerador mais recente…",
|
||||
|
||||
@@ -1369,6 +1369,61 @@
|
||||
"warning_upper": "ПРЕДУПРЕЖДЕНИЕ!",
|
||||
"website": "Веб-сайт",
|
||||
"window_opacity": "Прозрачность окна",
|
||||
"wiz_acrylic": "Эффект акрилового стекла",
|
||||
"wiz_acrylic_desc": "Полупрозрачное размытие панелей (Выкл. отключает)",
|
||||
"wiz_already_encrypted": "Кошелёк уже зашифрован",
|
||||
"wiz_already_encrypted_desc": "Ваш кошелёк защищён парольной фразой. Дополнительных действий не требуется.",
|
||||
"wiz_appearance": "Внешний вид",
|
||||
"wiz_bootstrap": "Начальная загрузка",
|
||||
"wiz_bootstrap_desc": "Загрузите начальный образ блокчейна, чтобы значительно ускорить первичную синхронизацию.\\n\\nВаш существующий файл wallet.dat НЕ будет изменён или заменён.",
|
||||
"wiz_bootstrap_failed": "Ошибка начальной загрузки",
|
||||
"wiz_confirm": "Подтверждение:",
|
||||
"wiz_continue": "Продолжить",
|
||||
"wiz_daemon_sending_stop": "Отправка команды остановки...",
|
||||
"wiz_daemon_stop_failed": "Демон не остановился — попробуйте вручную.",
|
||||
"wiz_daemon_stopped_ok": "Демон остановлен.",
|
||||
"wiz_daemon_waiting_stop": "Ожидание завершения работы демона...",
|
||||
"wiz_download_failed": "Ошибка загрузки",
|
||||
"wiz_encrypt_bg": "Шифрование завершится в фоновом режиме",
|
||||
"wiz_encrypt_continue": "Зашифровать и продолжить",
|
||||
"wiz_encrypt_desc": "Зашифруйте кошелёк, чтобы защитить приватные ключи парольной фразой.",
|
||||
"wiz_encrypt_warning": "Если вы потеряете парольную фразу, вы потеряете доступ к своим средствам.",
|
||||
"wiz_encryption": "Шифрование",
|
||||
"wiz_ext_daemon_running": "Запущен внешний демон",
|
||||
"wiz_ext_daemon_warning": "Его необходимо остановить перед загрузкой начального образа, иначе данные цепочки могут быть повреждены.",
|
||||
"wiz_level": "Уровень:",
|
||||
"wiz_lowspec_desc": "Отключить все тяжёлые визуальные эффекты",
|
||||
"wiz_off": "Выкл.",
|
||||
"wiz_pass_mismatch": "Парольные фразы не совпадают",
|
||||
"wiz_pass_spaces": "В парольной фразе есть пробелы в начале или конце — удалите их",
|
||||
"wiz_pass_too_short": "Парольная фраза должна содержать не менее 8 символов (%zu/8)",
|
||||
"wiz_passphrase": "Парольная фраза:",
|
||||
"wiz_pin_confirm": "Подтвердите PIN:",
|
||||
"wiz_pin_invalid": "PIN должен содержать 4–8 цифр",
|
||||
"wiz_pin_label": "PIN (4–8 цифр):",
|
||||
"wiz_pin_mismatch": "PIN-коды не совпадают",
|
||||
"wiz_pin_optional": "PIN быстрой разблокировки (необязательно)",
|
||||
"wiz_pin_title": "PIN быстрой разблокировки",
|
||||
"wiz_scanline_desc": "Эффект строк развёртки CRT в консоли",
|
||||
"wiz_skip": "Пропустить",
|
||||
"wiz_skip_confirm": "Продолжить БЕЗ шифрования? Ключи будут храниться незашифрованными — нажмите «Пропустить» ещё раз для подтверждения.",
|
||||
"wiz_step1": "Шаг 1",
|
||||
"wiz_step2": "Шаг 2",
|
||||
"wiz_step3": "Шаг 3",
|
||||
"wiz_stop_daemon": "Остановить демон",
|
||||
"wiz_strength": "Надёжность: %s",
|
||||
"wiz_strength_fair": "Средняя",
|
||||
"wiz_strength_good": "Хорошая",
|
||||
"wiz_strength_strong": "Надёжная",
|
||||
"wiz_strength_weak": "Слабая",
|
||||
"wiz_theme_builtin": "Встроенная",
|
||||
"wiz_theme_custom": "Своя",
|
||||
"wiz_theme_effects": "Визуальные эффекты темы",
|
||||
"wiz_theme_effects_desc": "Анимированные рамки, цветовая заливка",
|
||||
"wiz_theme_invalid": " (недопустимая)",
|
||||
"wiz_ui_opacity_desc": "Прозрачность карточек и боковой панели (1.0 = непрозрачно)",
|
||||
"wiz_welcome_sub": "Несколько быстрых настроек — и ваш полный узел готов.",
|
||||
"wiz_welcome_title": "Добро пожаловать в ObsidianDragon!",
|
||||
"wizard_daemon_start_failed": "Не удалось запустить демон — будет повторено автоматически",
|
||||
"xmrig_browse_releases": "Просмотреть все релизы…",
|
||||
"xmrig_checking": "Проверка наличия последней версии майнера…",
|
||||
|
||||
@@ -1369,6 +1369,61 @@
|
||||
"warning_upper": "警告!",
|
||||
"website": "网站",
|
||||
"window_opacity": "窗口透明度",
|
||||
"wiz_acrylic": "亚克力玻璃效果",
|
||||
"wiz_acrylic_desc": "面板上的半透明模糊(关闭则禁用)",
|
||||
"wiz_already_encrypted": "钱包已加密",
|
||||
"wiz_already_encrypted_desc": "您的钱包已使用密码短语进行保护。无需进一步操作。",
|
||||
"wiz_appearance": "外观",
|
||||
"wiz_bootstrap": "引导数据",
|
||||
"wiz_bootstrap_desc": "下载区块链引导数据以大幅加快初始同步速度。\n\n您现有的 wallet.dat 不会被修改或替换。",
|
||||
"wiz_bootstrap_failed": "引导数据失败",
|
||||
"wiz_confirm": "确认:",
|
||||
"wiz_continue": "继续",
|
||||
"wiz_daemon_sending_stop": "正在发送停止命令…",
|
||||
"wiz_daemon_stop_failed": "守护进程未停止——请尝试手动停止。",
|
||||
"wiz_daemon_stopped_ok": "守护进程已停止。",
|
||||
"wiz_daemon_waiting_stop": "正在等待守护进程关闭…",
|
||||
"wiz_download_failed": "下载失败",
|
||||
"wiz_encrypt_bg": "加密将在后台完成",
|
||||
"wiz_encrypt_continue": "加密并继续",
|
||||
"wiz_encrypt_desc": "加密您的钱包,用密码短语保护私钥。",
|
||||
"wiz_encrypt_warning": "如果您丢失密码短语,将无法访问您的资金。",
|
||||
"wiz_encryption": "加密",
|
||||
"wiz_ext_daemon_running": "外部守护进程正在运行",
|
||||
"wiz_ext_daemon_warning": "下载引导数据前必须先停止它,否则链数据可能会损坏。",
|
||||
"wiz_level": "级别:",
|
||||
"wiz_lowspec_desc": "禁用所有重度视觉效果",
|
||||
"wiz_off": "关闭",
|
||||
"wiz_pass_mismatch": "密码短语不匹配",
|
||||
"wiz_pass_spaces": "密码短语含有首尾空格——请将其删除",
|
||||
"wiz_pass_too_short": "密码短语至少需要 8 个字符 (%zu/8)",
|
||||
"wiz_passphrase": "密码短语:",
|
||||
"wiz_pin_confirm": "确认 PIN:",
|
||||
"wiz_pin_invalid": "PIN 必须为 4-8 位数字",
|
||||
"wiz_pin_label": "PIN(4-8 位数字):",
|
||||
"wiz_pin_mismatch": "PIN 不匹配",
|
||||
"wiz_pin_optional": "快速解锁 PIN(可选)",
|
||||
"wiz_pin_title": "快速解锁 PIN",
|
||||
"wiz_scanline_desc": "控制台中的 CRT 扫描线效果",
|
||||
"wiz_skip": "跳过",
|
||||
"wiz_skip_confirm": "确定不加密继续吗?私钥将以未加密方式存储——请再次点击“跳过”以确认。",
|
||||
"wiz_step1": "第 1 步",
|
||||
"wiz_step2": "第 2 步",
|
||||
"wiz_step3": "第 3 步",
|
||||
"wiz_stop_daemon": "停止守护进程",
|
||||
"wiz_strength": "强度:%s",
|
||||
"wiz_strength_fair": "一般",
|
||||
"wiz_strength_good": "良好",
|
||||
"wiz_strength_strong": "强",
|
||||
"wiz_strength_weak": "弱",
|
||||
"wiz_theme_builtin": "内置",
|
||||
"wiz_theme_custom": "自定义",
|
||||
"wiz_theme_effects": "主题视觉效果",
|
||||
"wiz_theme_effects_desc": "动态边框、色彩渲染",
|
||||
"wiz_theme_invalid": " (无效)",
|
||||
"wiz_ui_opacity_desc": "卡片与侧边栏透明度(1.0 = 不透明)",
|
||||
"wiz_welcome_sub": "只需几项快速设置,即可启用您的全节点。",
|
||||
"wiz_welcome_title": "欢迎使用 ObsidianDragon!",
|
||||
"wizard_daemon_start_failed": "启动守护进程失败 — 将自动重试",
|
||||
"xmrig_browse_releases": "浏览所有版本…",
|
||||
"xmrig_checking": "正在检查最新的矿工程序…",
|
||||
|
||||
@@ -189,14 +189,14 @@ void App::renderFirstRunWizard() {
|
||||
headerCy += logoSize + 8.0f * dp;
|
||||
|
||||
{
|
||||
const char* welcomeTitle = "Welcome to ObsidianDragon!";
|
||||
const char* welcomeTitle = TR("wiz_welcome_title");
|
||||
ImVec2 wts = titleFont->CalcTextSizeA(titleFont->LegacySize, FLT_MAX, 0, welcomeTitle);
|
||||
dl->AddText(titleFont, titleFont->LegacySize,
|
||||
ImVec2(winPos.x + (winSize.x - wts.x) * 0.5f, headerCy), textCol, welcomeTitle);
|
||||
headerCy += wts.y + 6.0f * dp;
|
||||
|
||||
// Warmer, less-sparse header: a one-line subtitle under the welcome (dimmed body).
|
||||
const char* welcomeSub = "A few quick choices and your full node is ready.";
|
||||
const char* welcomeSub = TR("wiz_welcome_sub");
|
||||
ImVec2 sts = bodyFont->CalcTextSizeA(bodyFont->LegacySize, FLT_MAX, 0, welcomeSub);
|
||||
dl->AddText(bodyFont, bodyFont->LegacySize,
|
||||
ImVec2(winPos.x + (winSize.x - sts.x) * 0.5f, headerCy), dimCol, welcomeSub);
|
||||
@@ -274,13 +274,13 @@ void App::renderFirstRunWizard() {
|
||||
{
|
||||
float iconW = iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0, stepIcon(state)).x;
|
||||
dl->AddText(iconFont, iconFont->LegacySize, ImVec2(cx, cy), dimCol, stepIcon(state));
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx + iconW + 4.0f * dp, cy), dimCol, "Step 1");
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx + iconW + 4.0f * dp, cy), dimCol, TR("wiz_step1"));
|
||||
cy += captionFont->LegacySize + 6.0f * dp;
|
||||
}
|
||||
|
||||
// Title
|
||||
{
|
||||
const char* t = "Appearance";
|
||||
const char* t = TR("wiz_appearance");
|
||||
dl->AddText(titleFont, titleFont->LegacySize, ImVec2(cx, cy), textCol, t);
|
||||
cy += titleFont->LegacySize + 10.0f * dp;
|
||||
}
|
||||
@@ -336,14 +336,14 @@ void App::renderFirstRunWizard() {
|
||||
for (const auto& skin : skins) {
|
||||
if (skin.id == skinMgr.activeSkinId()) { activePreview = skin.name; break; }
|
||||
}
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx, cy + 4.0f * dp), textCol, "Theme");
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx, cy + 4.0f * dp), textCol, TR("theme"));
|
||||
float comboX = cx + 110.0f * dp;
|
||||
float comboW = contentW - 110.0f * dp;
|
||||
ImGui::SetCursorScreenPos(ImVec2(comboX, cy));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f * dp);
|
||||
ImGui::SetNextItemWidth(comboW);
|
||||
if (ImGui::BeginCombo("##wiz_theme", activePreview.c_str())) {
|
||||
ImGui::TextDisabled("Built-in");
|
||||
ImGui::TextDisabled(TR("wiz_theme_builtin"));
|
||||
ImGui::Separator();
|
||||
for (const auto& skin : skins) {
|
||||
if (!skin.bundled) continue;
|
||||
@@ -359,7 +359,7 @@ void App::renderFirstRunWizard() {
|
||||
for (const auto& skin : skins) { if (!skin.bundled) { hasCustom = true; break; } }
|
||||
if (hasCustom) {
|
||||
ImGui::Spacing();
|
||||
ImGui::TextDisabled("Custom");
|
||||
ImGui::TextDisabled(TR("wiz_theme_custom"));
|
||||
ImGui::Separator();
|
||||
for (const auto& skin : skins) {
|
||||
if (skin.bundled) continue;
|
||||
@@ -367,7 +367,7 @@ void App::renderFirstRunWizard() {
|
||||
if (!skin.valid) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1,0.3f,0.3f,1));
|
||||
ImGui::BeginDisabled(true);
|
||||
ImGui::Selectable((skin.name + " (invalid)").c_str(), false);
|
||||
ImGui::Selectable((skin.name + TR("wiz_theme_invalid")).c_str(), false);
|
||||
ImGui::EndDisabled();
|
||||
ImGui::PopStyleColor();
|
||||
} else {
|
||||
@@ -395,7 +395,7 @@ void App::renderFirstRunWizard() {
|
||||
for (const auto& l : layouts) {
|
||||
if (l.id == wiz_balance_layout) { balPreview = l.name; break; }
|
||||
}
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx, cy + 4.0f * dp), textCol, "Balance Layout");
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx, cy + 4.0f * dp), textCol, TR("balance_layout"));
|
||||
float comboX = cx + 110.0f * dp;
|
||||
float comboW = contentW - 110.0f * dp;
|
||||
ImGui::SetCursorScreenPos(ImVec2(comboX, cy));
|
||||
@@ -426,7 +426,7 @@ void App::renderFirstRunWizard() {
|
||||
langNames.reserve(languages.size());
|
||||
for (const auto& lang : languages) langNames.push_back(lang.second.c_str());
|
||||
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx, cy + 4.0f * dp), textCol, "Language");
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx, cy + 4.0f * dp), textCol, TR("language"));
|
||||
float comboX = cx + 110.0f * dp;
|
||||
float comboW = contentW - 110.0f * dp;
|
||||
ImGui::SetCursorScreenPos(ImVec2(comboX, cy));
|
||||
@@ -497,10 +497,10 @@ void App::renderFirstRunWizard() {
|
||||
ImGui::SameLine();
|
||||
dl->AddText(bodyFont, bodyFont->LegacySize,
|
||||
ImVec2(ImGui::GetCursorScreenPos().x, cy + 2.0f * dp), textCol,
|
||||
"Low-spec mode");
|
||||
TR("low_spec_mode"));
|
||||
cy += bodyFont->LegacySize + 6.0f * dp;
|
||||
dl->AddText(captionFont, captionFont->LegacySize,
|
||||
ImVec2(cx + 28.0f * dp, cy), dimCol, "Disable all heavy visual effects");
|
||||
ImVec2(cx + 28.0f * dp, cy), dimCol, TR("wiz_lowspec_desc"));
|
||||
cy += captionFont->LegacySize + 16.0f * dp;
|
||||
|
||||
ImGui::BeginDisabled(wiz_low_spec);
|
||||
@@ -508,15 +508,15 @@ void App::renderFirstRunWizard() {
|
||||
// Acrylic blur slider
|
||||
dl->AddText(bodyFont, bodyFont->LegacySize,
|
||||
ImVec2(cx, cy + 2.0f * dp), textCol,
|
||||
"Acrylic glass effects");
|
||||
TR("wiz_acrylic"));
|
||||
cy += bodyFont->LegacySize + 4.0f * dp;
|
||||
dl->AddText(captionFont, captionFont->LegacySize,
|
||||
ImVec2(cx, cy), dimCol, "Translucent blur on panels (Off disables)");
|
||||
ImVec2(cx, cy), dimCol, TR("wiz_acrylic_desc"));
|
||||
cy += captionFont->LegacySize + 10.0f * dp;
|
||||
|
||||
{
|
||||
dl->AddText(captionFont, captionFont->LegacySize,
|
||||
ImVec2(cx + 4.0f * dp, cy), textCol, "Level:");
|
||||
ImVec2(cx + 4.0f * dp, cy), textCol, TR("wiz_level"));
|
||||
ImGui::SetCursorScreenPos(ImVec2(cx + 72.0f * dp, cy - 2.0f * dp));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f * dp);
|
||||
float sliderW = contentW - 72.0f * dp;
|
||||
@@ -524,7 +524,7 @@ void App::renderFirstRunWizard() {
|
||||
{
|
||||
char blur_fmt[16];
|
||||
if (wiz_blur_amount < 0.01f)
|
||||
snprintf(blur_fmt, sizeof(blur_fmt), "Off");
|
||||
snprintf(blur_fmt, sizeof(blur_fmt), TR("wiz_off"));
|
||||
else
|
||||
snprintf(blur_fmt, sizeof(blur_fmt), "%.0f%%%%", wiz_blur_amount * 25.0f);
|
||||
if (ImGui::SliderFloat("##wiz_blur", &wiz_blur_amount, 0.0f, 4.0f, blur_fmt,
|
||||
@@ -558,19 +558,19 @@ void App::renderFirstRunWizard() {
|
||||
ImGui::SameLine();
|
||||
dl->AddText(bodyFont, bodyFont->LegacySize,
|
||||
ImVec2(ImGui::GetCursorScreenPos().x, cy + 2.0f * dp), textCol,
|
||||
"Theme visual effects");
|
||||
TR("wiz_theme_effects"));
|
||||
cy += bodyFont->LegacySize + 6.0f * dp;
|
||||
dl->AddText(captionFont, captionFont->LegacySize,
|
||||
ImVec2(cx + 28.0f * dp, cy), dimCol, "Animated borders, color wash");
|
||||
ImVec2(cx + 28.0f * dp, cy), dimCol, TR("wiz_theme_effects_desc"));
|
||||
cy += captionFont->LegacySize + 16.0f * dp;
|
||||
|
||||
// UI Opacity slider
|
||||
dl->AddText(bodyFont, bodyFont->LegacySize,
|
||||
ImVec2(cx, cy + 2.0f * dp), textCol,
|
||||
"UI Opacity");
|
||||
TR("ui_opacity"));
|
||||
cy += bodyFont->LegacySize + 4.0f * dp;
|
||||
dl->AddText(captionFont, captionFont->LegacySize,
|
||||
ImVec2(cx, cy), dimCol, "Card & sidebar transparency (1.0 = solid)");
|
||||
ImVec2(cx, cy), dimCol, TR("wiz_ui_opacity_desc"));
|
||||
cy += captionFont->LegacySize + 10.0f * dp;
|
||||
{
|
||||
ImGui::SetCursorScreenPos(ImVec2(cx, cy - 2.0f * dp));
|
||||
@@ -599,10 +599,10 @@ void App::renderFirstRunWizard() {
|
||||
ImGui::SameLine();
|
||||
dl->AddText(bodyFont, bodyFont->LegacySize,
|
||||
ImVec2(ImGui::GetCursorScreenPos().x, cy + 2.0f * dp), textCol,
|
||||
"Console scanline");
|
||||
TR("console_scanline"));
|
||||
cy += bodyFont->LegacySize + 6.0f * dp;
|
||||
dl->AddText(captionFont, captionFont->LegacySize,
|
||||
ImVec2(cx + 28.0f * dp, cy), dimCol, "CRT scanline effect in console");
|
||||
ImVec2(cx + 28.0f * dp, cy), dimCol, TR("wiz_scanline_desc"));
|
||||
cy += captionFont->LegacySize + 24.0f * dp;
|
||||
|
||||
ImGui::EndDisabled(); // low-spec
|
||||
@@ -620,7 +620,7 @@ void App::renderFirstRunWizard() {
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::ColorConvertU32ToFloat4(ui::material::PrimaryVariant()));
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::ColorConvertU32ToFloat4(ui::material::OnPrimary()));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 8.0f * dp);
|
||||
if (ui::material::TactileButton("Continue##app", ImVec2(btnW, btnH))) {
|
||||
if (ui::material::TactileButton(TR("wiz_continue"), ImVec2(btnW, btnH))) {
|
||||
// Save appearance choices, advance to Bootstrap
|
||||
settings_->setAcrylicEnabled(wiz_blur_amount > 0.001f);
|
||||
settings_->setAcrylicQuality(wiz_blur_amount > 0.001f
|
||||
@@ -667,23 +667,23 @@ void App::renderFirstRunWizard() {
|
||||
float iconW = iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0, stepIcon(state)).x;
|
||||
dl->AddText(iconFont, iconFont->LegacySize, ImVec2(cx, cy), dimCol, stepIcon(state));
|
||||
float labelX = cx + iconW + 4.0f * dp;
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(labelX, cy), dimCol, "Step 2");
|
||||
float step2W = captionFont->CalcTextSizeA(captionFont->LegacySize, FLT_MAX, 0, "Step 2").x;
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(labelX, cy), dimCol, TR("wiz_step2"));
|
||||
float step2W = captionFont->CalcTextSizeA(captionFont->LegacySize, FLT_MAX, 0, TR("wiz_step2")).x;
|
||||
float titleX = labelX + step2W + 12.0f * dp;
|
||||
dl->AddText(bodyFont, bodyFont->LegacySize, ImVec2(titleX, cy), dimCol, "Bootstrap");
|
||||
dl->AddText(bodyFont, bodyFont->LegacySize, ImVec2(titleX, cy), dimCol, TR("wiz_bootstrap"));
|
||||
cy += captionFont->LegacySize + 4.0f * dp;
|
||||
} else {
|
||||
// Step indicator
|
||||
{
|
||||
float iconW = iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0, stepIcon(state)).x;
|
||||
dl->AddText(iconFont, iconFont->LegacySize, ImVec2(cx, cy), dimCol, stepIcon(state));
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx + iconW + 4.0f * dp, cy), dimCol, "Step 2");
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx + iconW + 4.0f * dp, cy), dimCol, TR("wiz_step2"));
|
||||
cy += captionFont->LegacySize + 4.0f * dp;
|
||||
}
|
||||
|
||||
// Title
|
||||
{
|
||||
const char* t = "Bootstrap";
|
||||
const char* t = TR("wiz_bootstrap");
|
||||
dl->AddText(titleFont, titleFont->LegacySize, ImVec2(cx, cy), textCol, t);
|
||||
cy += titleFont->LegacySize + 6.0f * dp;
|
||||
}
|
||||
@@ -706,11 +706,11 @@ void App::renderFirstRunWizard() {
|
||||
|
||||
const char* statusTitle;
|
||||
if (prog.state == util::Bootstrap::State::Downloading)
|
||||
statusTitle = "Downloading bootstrap...";
|
||||
statusTitle = TR("bootstrap_downloading");
|
||||
else if (prog.state == util::Bootstrap::State::Verifying)
|
||||
statusTitle = "Verifying checksums...";
|
||||
statusTitle = TR("bootstrap_verifying");
|
||||
else
|
||||
statusTitle = "Extracting blockchain data...";
|
||||
statusTitle = TR("bootstrap_extracting");
|
||||
dl->AddText(bodyFont, bodyFont->LegacySize, ImVec2(cx, cy), textCol, statusTitle);
|
||||
cy += bodyFont->LegacySize + 12.0f * dp;
|
||||
|
||||
@@ -739,7 +739,7 @@ void App::renderFirstRunWizard() {
|
||||
|
||||
if (prog.state == util::Bootstrap::State::Extracting) {
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx, cy),
|
||||
dimCol, "(wallet.dat is protected)");
|
||||
dimCol, TR("bootstrap_wallet_protected"));
|
||||
cy += captionFont->LegacySize + 6.0f * dp;
|
||||
}
|
||||
|
||||
@@ -755,9 +755,9 @@ void App::renderFirstRunWizard() {
|
||||
dl->AddCircleFilled(ImVec2(cx + dotR, cy + captionFont->LegacySize * 0.5f),
|
||||
dotR, dotCol);
|
||||
const char* label = daemonUp ? (dStatus.find("Stopping") != std::string::npos
|
||||
? "Daemon stopping..."
|
||||
: "Daemon running")
|
||||
: "Daemon stopped";
|
||||
? TR("bootstrap_daemon_stopping")
|
||||
: TR("bootstrap_daemon_running"))
|
||||
: TR("bootstrap_daemon_stopped");
|
||||
dl->AddText(captionFont, captionFont->LegacySize,
|
||||
ImVec2(cx + dotR * 2.0f + 6.0f * dp, cy),
|
||||
(dimCol & 0x00FFFFFF) | IM_COL32(0,0,0,140), label);
|
||||
@@ -772,7 +772,7 @@ void App::renderFirstRunWizard() {
|
||||
float cancelBX = rightX + (colW - cancelW) * 0.5f;
|
||||
ImGui::SetCursorScreenPos(ImVec2(cancelBX, cy));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 8.0f * dp);
|
||||
if (ui::material::TactileButton("Cancel##bs", ImVec2(cancelW, cancelH))) {
|
||||
if (ui::material::TactileButton(TR("cancel"), ImVec2(cancelW, cancelH))) {
|
||||
bootstrap_->cancel();
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
@@ -799,10 +799,10 @@ void App::renderFirstRunWizard() {
|
||||
errMsg = bootstrap_->getProgress().error;
|
||||
bootstrap_.reset();
|
||||
}
|
||||
if (errMsg.empty()) errMsg = "Bootstrap failed";
|
||||
if (errMsg.empty()) errMsg = TR("wiz_bootstrap_failed");
|
||||
|
||||
dl->AddText(bodyFont, bodyFont->LegacySize, ImVec2(cx, cy),
|
||||
ui::material::Error(), "Download Failed");
|
||||
ui::material::Error(), TR("wiz_download_failed"));
|
||||
cy += bodyFont->LegacySize + 8.0f * dp;
|
||||
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx, cy), textCol,
|
||||
@@ -821,7 +821,7 @@ void App::renderFirstRunWizard() {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::ColorConvertU32ToFloat4(ui::material::OnPrimary()));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 8.0f * dp);
|
||||
ImGui::BeginDisabled(!supportsFullNodeLifecycleActions());
|
||||
if (ui::material::TactileButton("Retry##bs", ImVec2(btnW2, btnH2))) {
|
||||
if (ui::material::TactileButton(TR("retry"), ImVec2(btnW2, btnH2))) {
|
||||
// Stop embedded daemon before bootstrap to avoid chain data corruption
|
||||
stopDaemonForBootstrap();
|
||||
bootstrap_ = std::make_unique<util::Bootstrap>();
|
||||
@@ -835,7 +835,7 @@ void App::renderFirstRunWizard() {
|
||||
|
||||
ImGui::SetCursorScreenPos(ImVec2(bx + btnW2 + 12.0f * dp, cy));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 8.0f * dp);
|
||||
if (ui::material::TactileButton("Skip##bsfail", ImVec2(btnW2, btnH2))) {
|
||||
if (ui::material::TactileButton(TR("wiz_skip"), ImVec2(btnW2, btnH2))) {
|
||||
wizard_phase_ = WizardPhase::EncryptOffer;
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
@@ -878,11 +878,11 @@ void App::renderFirstRunWizard() {
|
||||
{
|
||||
float iw = iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0, ICON_MD_WARNING).x;
|
||||
dl->AddText(iconFont, iconFont->LegacySize, ImVec2(cx, cy), warnCol, ICON_MD_WARNING);
|
||||
dl->AddText(bodyFont, bodyFont->LegacySize, ImVec2(cx + iw + 4.0f * dp, cy), warnCol, "External daemon running");
|
||||
dl->AddText(bodyFont, bodyFont->LegacySize, ImVec2(cx + iw + 4.0f * dp, cy), warnCol, TR("wiz_ext_daemon_running"));
|
||||
}
|
||||
cy += bodyFont->LegacySize + 4.0f * dp;
|
||||
{
|
||||
const char* warnBody = "It must be stopped before downloading a bootstrap, otherwise chain data could be corrupted.";
|
||||
const char* warnBody = TR("wiz_ext_daemon_warning");
|
||||
ImVec2 ws = captionFont->CalcTextSizeA(captionFont->LegacySize, FLT_MAX, contentW, warnBody);
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx, cy), textCol, warnBody, nullptr, contentW);
|
||||
cy += ws.y + 12.0f * dp;
|
||||
@@ -905,9 +905,9 @@ void App::renderFirstRunWizard() {
|
||||
IM_COL32(220, 60, 60, 255)));
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 255, 255, 255));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 8.0f * dp);
|
||||
if (ui::material::TactileButton("Stop Daemon##wiz", ImVec2(stopW, btnH2))) {
|
||||
if (ui::material::TactileButton(TR("wiz_stop_daemon"), ImVec2(stopW, btnH2))) {
|
||||
wizard_stopping_external_ = true;
|
||||
wizard_stop_status_ = "Sending stop command...";
|
||||
wizard_stop_status_ = TR("wiz_daemon_sending_stop");
|
||||
async_tasks_.submit("wizard-stop-external-daemon", [this](const util::AsyncTaskManager::Token& token) {
|
||||
auto config = rpc::Connection::autoDetectConfig();
|
||||
if (!config.rpcuser.empty() && !config.rpcpassword.empty()) {
|
||||
@@ -919,17 +919,17 @@ void App::renderFirstRunWizard() {
|
||||
tmp_rpc->disconnect();
|
||||
}
|
||||
}
|
||||
wizard_stop_status_ = "Waiting for daemon to shut down...";
|
||||
wizard_stop_status_ = TR("wiz_daemon_waiting_stop");
|
||||
for (int i = 0; i < 60 && !token.cancelled(); i++) {
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
if (!daemon::EmbeddedDaemon::isRpcPortInUse()) {
|
||||
wizard_stop_status_ = "Daemon stopped.";
|
||||
wizard_stop_status_ = TR("wiz_daemon_stopped_ok");
|
||||
wizard_stopping_external_ = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (token.cancelled()) return;
|
||||
wizard_stop_status_ = "Daemon did not stop — try manually.";
|
||||
wizard_stop_status_ = TR("wiz_daemon_stop_failed");
|
||||
wizard_stopping_external_ = false;
|
||||
});
|
||||
}
|
||||
@@ -938,7 +938,7 @@ void App::renderFirstRunWizard() {
|
||||
|
||||
ImGui::SetCursorScreenPos(ImVec2(bx + stopW + 12.0f * dp, cy));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 8.0f * dp);
|
||||
if (ui::material::TactileButton("Skip##extd", ImVec2(skipW2, btnH2))) {
|
||||
if (ui::material::TactileButton(TR("wiz_skip"), ImVec2(skipW2, btnH2))) {
|
||||
wizard_phase_ = WizardPhase::EncryptOffer;
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
@@ -947,7 +947,7 @@ void App::renderFirstRunWizard() {
|
||||
} else {
|
||||
// --- Normal bootstrap offer ---
|
||||
{
|
||||
const char* bsText = "Download a blockchain bootstrap to dramatically speed up initial sync.\n\nYour existing wallet.dat will NOT be modified or replaced.";
|
||||
const char* bsText = TR("wiz_bootstrap_desc");
|
||||
ImVec2 bsSize = bodyFont->CalcTextSizeA(bodyFont->LegacySize, FLT_MAX, contentW, bsText);
|
||||
dl->AddText(bodyFont, bodyFont->LegacySize, ImVec2(cx, cy), textCol, bsText, nullptr, contentW);
|
||||
cy += bsSize.y + 8.0f * dp;
|
||||
@@ -960,7 +960,7 @@ void App::renderFirstRunWizard() {
|
||||
ImU32 warnCol = (textCol & 0x00FFFFFF) | ((ImU32)(255 * warnOpacity) << 24);
|
||||
float iw = iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0, ICON_MD_WARNING).x;
|
||||
dl->AddText(iconFont, iconFont->LegacySize, ImVec2(cx, cy), warnCol, ICON_MD_WARNING);
|
||||
const char* twText = "Only use bootstrap.dragonx.is or bootstrap2.dragonx.is. Using files from untrusted sources could compromise your node.";
|
||||
const char* twText = TR("bootstrap_trust_warning");
|
||||
float twWrap = contentW - iw - 4.0f * dp;
|
||||
ImVec2 twSize = captionFont->CalcTextSizeA(captionFont->LegacySize, FLT_MAX, twWrap, twText);
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx + iw + 4.0f * dp, cy), warnCol, twText, nullptr, twWrap);
|
||||
@@ -979,9 +979,9 @@ void App::renderFirstRunWizard() {
|
||||
dl->AddCircleFilled(ImVec2(cx + dotR, cy + captionFont->LegacySize * 0.5f),
|
||||
dotR, dotCol);
|
||||
const char* label = daemonUp ? (dStatus.find("Stopping") != std::string::npos
|
||||
? "Daemon stopping..."
|
||||
: "Daemon running")
|
||||
: "Daemon stopped";
|
||||
? TR("bootstrap_daemon_stopping")
|
||||
: TR("bootstrap_daemon_running"))
|
||||
: TR("bootstrap_daemon_stopped");
|
||||
dl->AddText(captionFont, captionFont->LegacySize,
|
||||
ImVec2(cx + dotR * 2.0f + 6.0f * dp, cy),
|
||||
(dimCol & 0x00FFFFFF) | IM_COL32(0,0,0,140), label);
|
||||
@@ -1004,7 +1004,7 @@ void App::renderFirstRunWizard() {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::ColorConvertU32ToFloat4(ui::material::OnPrimary()));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 8.0f * dp);
|
||||
ImGui::BeginDisabled(!supportsFullNodeLifecycleActions());
|
||||
if (ui::material::TactileButton("Download##bs", ImVec2(dlBtnW, btnH2))) {
|
||||
if (ui::material::TactileButton(TR("download"), ImVec2(dlBtnW, btnH2))) {
|
||||
// Stop embedded daemon before bootstrap to avoid chain data corruption
|
||||
stopDaemonForBootstrap();
|
||||
bootstrap_ = std::make_unique<util::Bootstrap>();
|
||||
@@ -1023,7 +1023,7 @@ void App::renderFirstRunWizard() {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::ColorConvertU32ToFloat4(ui::material::OnSurface()));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 8.0f * dp);
|
||||
ImGui::BeginDisabled(!supportsFullNodeLifecycleActions());
|
||||
if (ui::material::TactileButton("Mirror##bs_mirror", ImVec2(mirrorW, btnH2))) {
|
||||
if (ui::material::TactileButton(TR("bootstrap_mirror"), ImVec2(mirrorW, btnH2))) {
|
||||
stopDaemonForBootstrap();
|
||||
bootstrap_ = std::make_unique<util::Bootstrap>();
|
||||
std::string dataDir = util::Platform::getDragonXDataDir();
|
||||
@@ -1033,7 +1033,7 @@ void App::renderFirstRunWizard() {
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ui::material::Tooltip("Download from mirror (bootstrap2.dragonx.is).\nUse this if the main download is slow or failing.");
|
||||
ui::material::Tooltip(TR("bootstrap_mirror_tooltip"));
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleColor(3);
|
||||
@@ -1041,7 +1041,7 @@ void App::renderFirstRunWizard() {
|
||||
// --- Skip button ---
|
||||
ImGui::SetCursorScreenPos(ImVec2(bx + dlBtnW + 8.0f * dp + mirrorW + 8.0f * dp, cy));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 8.0f * dp);
|
||||
if (ui::material::TactileButton("Skip##bs", ImVec2(skipW2, btnH2))) {
|
||||
if (ui::material::TactileButton(TR("wiz_skip"), ImVec2(skipW2, btnH2))) {
|
||||
wizard_phase_ = WizardPhase::EncryptOffer;
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
@@ -1093,14 +1093,14 @@ void App::renderFirstRunWizard() {
|
||||
{
|
||||
float iconW = iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0, stepIcon(state)).x;
|
||||
dl->AddText(iconFont, iconFont->LegacySize, ImVec2(cx, cy), dimCol, stepIcon(state));
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx + iconW + 4.0f * dp, cy), dimCol, "Step 3");
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx + iconW + 4.0f * dp, cy), dimCol, TR("wiz_step3"));
|
||||
cy += captionFont->LegacySize + 4.0f * dp;
|
||||
}
|
||||
|
||||
// Title (changes for PinSetup sub-state)
|
||||
{
|
||||
const char* t = (isFocused && wizard_phase_ == WizardPhase::PinSetup)
|
||||
? "Quick-Unlock PIN" : "Encryption";
|
||||
? TR("wiz_pin_title") : TR("wiz_encryption");
|
||||
dl->AddText(titleFont, titleFont->LegacySize, ImVec2(cx, cy), textCol, t);
|
||||
cy += titleFont->LegacySize + 6.0f * dp;
|
||||
}
|
||||
@@ -1117,11 +1117,11 @@ void App::renderFirstRunWizard() {
|
||||
ImU32 okCol = ui::material::Secondary();
|
||||
float iw = iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0, ICON_MD_VERIFIED_USER).x;
|
||||
dl->AddText(iconFont, iconFont->LegacySize, ImVec2(cx, cy), okCol, ICON_MD_VERIFIED_USER);
|
||||
dl->AddText(bodyFont, bodyFont->LegacySize, ImVec2(cx + iw + 6.0f * dp, cy), okCol, "Wallet is already encrypted");
|
||||
dl->AddText(bodyFont, bodyFont->LegacySize, ImVec2(cx + iw + 6.0f * dp, cy), okCol, TR("wiz_already_encrypted"));
|
||||
cy += bodyFont->LegacySize + 12.0f * dp;
|
||||
}
|
||||
{
|
||||
const char* desc = "Your wallet is protected with a passphrase. No further action is needed.";
|
||||
const char* desc = TR("wiz_already_encrypted_desc");
|
||||
ImVec2 ds = bodyFont->CalcTextSizeA(bodyFont->LegacySize, FLT_MAX, contentW, desc);
|
||||
dl->AddText(bodyFont, bodyFont->LegacySize, ImVec2(cx, cy), textCol, desc, nullptr, contentW);
|
||||
cy += ds.y + 20.0f * dp;
|
||||
@@ -1136,7 +1136,7 @@ void App::renderFirstRunWizard() {
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::ColorConvertU32ToFloat4(ui::material::PrimaryVariant()));
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::ColorConvertU32ToFloat4(ui::material::OnPrimary()));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 8.0f * dp);
|
||||
if (ui::material::TactileButton("Continue##encok", ImVec2(btnW2, btnH2))) {
|
||||
if (ui::material::TactileButton(TR("wiz_continue"), ImVec2(btnW2, btnH2))) {
|
||||
wizard_phase_ = WizardPhase::Done;
|
||||
settings_->setWizardCompleted(true);
|
||||
settings_->save();
|
||||
@@ -1148,7 +1148,7 @@ void App::renderFirstRunWizard() {
|
||||
} else if (isFocused) {
|
||||
// ---- Encryption offer + optional PIN (combined) ----
|
||||
{
|
||||
const char* encDesc = "Encrypt your wallet to protect private keys with a passphrase.";
|
||||
const char* encDesc = TR("wiz_encrypt_desc");
|
||||
ImVec2 edSize = bodyFont->CalcTextSizeA(bodyFont->LegacySize, FLT_MAX, contentW, encDesc);
|
||||
dl->AddText(bodyFont, bodyFont->LegacySize, ImVec2(cx, cy), textCol, encDesc, nullptr, contentW);
|
||||
cy += edSize.y + 6.0f * dp;
|
||||
@@ -1157,7 +1157,7 @@ void App::renderFirstRunWizard() {
|
||||
ImU32 warnCol2 = ui::material::Warning();
|
||||
float iw = iconFont->CalcTextSizeA(iconFont->LegacySize, FLT_MAX, 0, ICON_MD_WARNING).x;
|
||||
dl->AddText(iconFont, iconFont->LegacySize, ImVec2(cx, cy), warnCol2, ICON_MD_WARNING);
|
||||
const char* warnLoss = "If you lose your passphrase, you lose access to your funds.";
|
||||
const char* warnLoss = TR("wiz_encrypt_warning");
|
||||
float wlWrap = contentW - iw - 4.0f * dp;
|
||||
ImVec2 wlSize = bodyFont->CalcTextSizeA(bodyFont->LegacySize, FLT_MAX, wlWrap, warnLoss);
|
||||
dl->AddText(bodyFont, bodyFont->LegacySize, ImVec2(cx + iw + 4.0f * dp, cy), warnCol2, warnLoss, nullptr, wlWrap);
|
||||
@@ -1165,7 +1165,7 @@ void App::renderFirstRunWizard() {
|
||||
}
|
||||
|
||||
// Passphrase input
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx, cy), dimCol, "Passphrase:");
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx, cy), dimCol, TR("wiz_passphrase"));
|
||||
cy += captionFont->LegacySize + 4.0f * dp;
|
||||
|
||||
ImGui::SetCursorScreenPos(ImVec2(cx, cy));
|
||||
@@ -1177,7 +1177,7 @@ void App::renderFirstRunWizard() {
|
||||
ImGui::PopItemWidth();
|
||||
cy += 36.0f * dp + 6.0f * dp;
|
||||
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx, cy), dimCol, "Confirm:");
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx, cy), dimCol, TR("wiz_confirm"));
|
||||
cy += captionFont->LegacySize + 4.0f * dp;
|
||||
|
||||
ImGui::SetCursorScreenPos(ImVec2(cx, cy));
|
||||
@@ -1192,16 +1192,16 @@ void App::renderFirstRunWizard() {
|
||||
// Strength meter
|
||||
{
|
||||
size_t len = strlen(encrypt_pass_buf_);
|
||||
const char* strengthLabel = "Weak";
|
||||
const char* strengthLabel = TR("wiz_strength_weak");
|
||||
ImU32 strengthCol = ui::material::Error();
|
||||
float strengthPct = 0.25f;
|
||||
|
||||
if (len >= 16) {
|
||||
strengthLabel = "Strong"; strengthCol = ui::material::Secondary(); strengthPct = 1.0f;
|
||||
strengthLabel = TR("wiz_strength_strong"); strengthCol = ui::material::Secondary(); strengthPct = 1.0f;
|
||||
} else if (len >= 12) {
|
||||
strengthLabel = "Good"; strengthCol = ui::material::Secondary(); strengthPct = 0.75f;
|
||||
strengthLabel = TR("wiz_strength_good"); strengthCol = ui::material::Secondary(); strengthPct = 0.75f;
|
||||
} else if (len >= 8) {
|
||||
strengthLabel = "Fair"; strengthCol = ui::material::Warning(); strengthPct = 0.5f;
|
||||
strengthLabel = TR("wiz_strength_fair"); strengthCol = ui::material::Warning(); strengthPct = 0.5f;
|
||||
}
|
||||
|
||||
float sBarH = 4.0f * dp, sBarR = 2.0f * dp;
|
||||
@@ -1214,7 +1214,7 @@ void App::renderFirstRunWizard() {
|
||||
cy += sBarH + 4.0f * dp;
|
||||
|
||||
char slabel[64];
|
||||
snprintf(slabel, sizeof(slabel), "Strength: %s", strengthLabel);
|
||||
snprintf(slabel, sizeof(slabel), TR("wiz_strength"), strengthLabel);
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx, cy), dimCol, slabel);
|
||||
cy += captionFont->LegacySize + 10.0f * dp;
|
||||
}
|
||||
@@ -1224,14 +1224,14 @@ void App::renderFirstRunWizard() {
|
||||
size_t pLen = strlen(encrypt_pass_buf_);
|
||||
if (pLen > 0 && pLen < 8) {
|
||||
char fb[80];
|
||||
snprintf(fb, sizeof(fb), "Passphrase must be at least 8 characters (%zu/8)", pLen);
|
||||
snprintf(fb, sizeof(fb), TR("wiz_pass_too_short"), pLen);
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx, cy),
|
||||
ui::material::Error(), fb);
|
||||
cy += captionFont->LegacySize + 6.0f * dp;
|
||||
} else if (pLen >= 8 && strlen(encrypt_confirm_buf_) > 0 &&
|
||||
strcmp(encrypt_pass_buf_, encrypt_confirm_buf_) != 0) {
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx, cy),
|
||||
ui::material::Error(), "Passphrases do not match");
|
||||
ui::material::Error(), TR("wiz_pass_mismatch"));
|
||||
cy += captionFont->LegacySize + 6.0f * dp;
|
||||
}
|
||||
}
|
||||
@@ -1243,12 +1243,12 @@ void App::renderFirstRunWizard() {
|
||||
cy += 8.0f * dp;
|
||||
|
||||
{
|
||||
const char* pinTitle = "Quick-Unlock PIN (optional)";
|
||||
const char* pinTitle = TR("wiz_pin_optional");
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx, cy), textCol, pinTitle);
|
||||
cy += captionFont->LegacySize + 4.0f * dp;
|
||||
}
|
||||
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx, cy), dimCol, "PIN (4-8 digits):");
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx, cy), dimCol, TR("wiz_pin_label"));
|
||||
cy += captionFont->LegacySize + 4.0f * dp;
|
||||
|
||||
ImGui::SetCursorScreenPos(ImVec2(cx, cy));
|
||||
@@ -1260,7 +1260,7 @@ void App::renderFirstRunWizard() {
|
||||
ImGui::PopItemWidth();
|
||||
cy += 36.0f * dp + 6.0f * dp;
|
||||
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx, cy), dimCol, "Confirm PIN:");
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx, cy), dimCol, TR("wiz_pin_confirm"));
|
||||
cy += captionFont->LegacySize + 4.0f * dp;
|
||||
|
||||
ImGui::SetCursorScreenPos(ImVec2(cx, cy));
|
||||
@@ -1277,12 +1277,12 @@ void App::renderFirstRunWizard() {
|
||||
std::string pinStr(wizard_pin_buf_);
|
||||
if (!pinStr.empty() && !util::SecureVault::isValidPin(pinStr)) {
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx, cy),
|
||||
ui::material::Error(), "PIN must be 4-8 digits");
|
||||
ui::material::Error(), TR("wiz_pin_invalid"));
|
||||
cy += captionFont->LegacySize + 6.0f * dp;
|
||||
} else if (!pinStr.empty() && strlen(wizard_pin_confirm_buf_) > 0 &&
|
||||
pinStr != std::string(wizard_pin_confirm_buf_)) {
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx, cy),
|
||||
ui::material::Error(), "PINs do not match");
|
||||
ui::material::Error(), TR("wiz_pin_mismatch"));
|
||||
cy += captionFont->LegacySize + 6.0f * dp;
|
||||
}
|
||||
}
|
||||
@@ -1303,7 +1303,7 @@ void App::renderFirstRunWizard() {
|
||||
}
|
||||
if (passEdgeSpace) {
|
||||
dl->AddText(captionFont, captionFont->LegacySize, ImVec2(cx, cy),
|
||||
ui::material::Error(), "Passphrase has leading/trailing spaces — remove them");
|
||||
ui::material::Error(), TR("wiz_pass_spaces"));
|
||||
cy += captionFont->LegacySize + 6.0f * dp;
|
||||
}
|
||||
|
||||
@@ -1333,7 +1333,7 @@ void App::renderFirstRunWizard() {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::ColorConvertU32ToFloat4(ui::material::OnPrimary()));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 8.0f * dp);
|
||||
ImGui::BeginDisabled(!canEncrypt);
|
||||
if (ui::material::TactileButton("Encrypt & Continue##wiz", ImVec2(encBtnW, btnH2))) {
|
||||
if (ui::material::TactileButton(TR("wiz_encrypt_continue"), ImVec2(encBtnW, btnH2))) {
|
||||
// Save passphrase + optional PIN for background processing
|
||||
wallet_security_.beginDeferredEncryption(
|
||||
std::string(encrypt_pass_buf_),
|
||||
@@ -1356,7 +1356,7 @@ void App::renderFirstRunWizard() {
|
||||
wizard_phase_ = WizardPhase::Done;
|
||||
settings_->setWizardCompleted(true);
|
||||
settings_->save();
|
||||
ui::Notifications::instance().info("Encryption will complete in the background");
|
||||
ui::Notifications::instance().info(TR("wiz_encrypt_bg"));
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::PopStyleVar();
|
||||
@@ -1364,12 +1364,12 @@ void App::renderFirstRunWizard() {
|
||||
|
||||
ImGui::SetCursorScreenPos(ImVec2(bx + encBtnW + 12.0f * dp, cy));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 8.0f * dp);
|
||||
if (ui::material::TactileButton("Skip##enc", ImVec2(skipW2, btnH2))) {
|
||||
if (ui::material::TactileButton(TR("wiz_skip"), ImVec2(skipW2, btnH2))) {
|
||||
static bool s_skipEncConfirm = false;
|
||||
if (!s_skipEncConfirm) {
|
||||
// Skipping stores private keys UNENCRYPTED — require a confirming second click.
|
||||
s_skipEncConfirm = true;
|
||||
encrypt_status_ = "Continue WITHOUT encryption? Keys will be stored unencrypted — click Skip again to confirm.";
|
||||
encrypt_status_ = TR("wiz_skip_confirm");
|
||||
} else {
|
||||
s_skipEncConfirm = false;
|
||||
wizard_phase_ = WizardPhase::Done;
|
||||
@@ -1389,7 +1389,7 @@ void App::renderFirstRunWizard() {
|
||||
}
|
||||
} else {
|
||||
// ---- Not focused: show static description ----
|
||||
const char* encDesc = "Encrypt your wallet to protect private keys with a passphrase.";
|
||||
const char* encDesc = TR("wiz_encrypt_desc");
|
||||
ImVec2 edSize = bodyFont->CalcTextSizeA(bodyFont->LegacySize, FLT_MAX, contentW, encDesc);
|
||||
dl->AddText(bodyFont, bodyFont->LegacySize, ImVec2(cx, cy), dimCol, encDesc, nullptr, contentW);
|
||||
cy += edSize.y + 6.0f * dp;
|
||||
|
||||
@@ -464,6 +464,63 @@ void I18n::loadBuiltinEnglish()
|
||||
strings_["tt_reduce_motion"] = "Disable animated transitions and balance lerp for accessibility";
|
||||
strings_["ago"] = "ago";
|
||||
strings_["wizard_daemon_start_failed"] = "Failed to start daemon \xe2\x80\x94 it will be retried automatically";
|
||||
// First-run wizard (app_wizard.cpp). Bootstrap/appearance labels reuse existing keys; these are
|
||||
// the wizard-specific strings.
|
||||
strings_["wiz_welcome_title"] = "Welcome to ObsidianDragon!";
|
||||
strings_["wiz_welcome_sub"] = "A few quick choices and your full node is ready.";
|
||||
strings_["wiz_step1"] = "Step 1";
|
||||
strings_["wiz_step2"] = "Step 2";
|
||||
strings_["wiz_step3"] = "Step 3";
|
||||
strings_["wiz_appearance"] = "Appearance";
|
||||
strings_["wiz_theme_builtin"] = "Built-in";
|
||||
strings_["wiz_theme_custom"] = "Custom";
|
||||
strings_["wiz_theme_invalid"] = " (invalid)";
|
||||
strings_["wiz_lowspec_desc"] = "Disable all heavy visual effects";
|
||||
strings_["wiz_acrylic"] = "Acrylic glass effects";
|
||||
strings_["wiz_acrylic_desc"] = "Translucent blur on panels (Off disables)";
|
||||
strings_["wiz_level"] = "Level:";
|
||||
strings_["wiz_off"] = "Off";
|
||||
strings_["wiz_theme_effects"] = "Theme visual effects";
|
||||
strings_["wiz_theme_effects_desc"] = "Animated borders, color wash";
|
||||
strings_["wiz_ui_opacity_desc"] = "Card & sidebar transparency (1.0 = solid)";
|
||||
strings_["wiz_scanline_desc"] = "CRT scanline effect in console";
|
||||
strings_["wiz_bootstrap"] = "Bootstrap";
|
||||
strings_["wiz_bootstrap_desc"] = "Download a blockchain bootstrap to dramatically speed up initial sync.\n\nYour existing wallet.dat will NOT be modified or replaced.";
|
||||
strings_["wiz_skip"] = "Skip";
|
||||
strings_["wiz_bootstrap_failed"] = "Bootstrap failed";
|
||||
strings_["wiz_download_failed"] = "Download Failed";
|
||||
strings_["wiz_ext_daemon_running"] = "External daemon running";
|
||||
strings_["wiz_ext_daemon_warning"] = "It must be stopped before downloading a bootstrap, otherwise chain data could be corrupted.";
|
||||
strings_["wiz_stop_daemon"] = "Stop Daemon";
|
||||
strings_["wiz_daemon_sending_stop"] = "Sending stop command...";
|
||||
strings_["wiz_daemon_waiting_stop"] = "Waiting for daemon to shut down...";
|
||||
strings_["wiz_daemon_stopped_ok"] = "Daemon stopped.";
|
||||
strings_["wiz_daemon_stop_failed"] = "Daemon did not stop \xe2\x80\x94 try manually.";
|
||||
strings_["wiz_encryption"] = "Encryption";
|
||||
strings_["wiz_pin_title"] = "Quick-Unlock PIN";
|
||||
strings_["wiz_already_encrypted"] = "Wallet is already encrypted";
|
||||
strings_["wiz_already_encrypted_desc"] = "Your wallet is protected with a passphrase. No further action is needed.";
|
||||
strings_["wiz_continue"] = "Continue";
|
||||
strings_["wiz_encrypt_desc"] = "Encrypt your wallet to protect private keys with a passphrase.";
|
||||
strings_["wiz_encrypt_warning"] = "If you lose your passphrase, you lose access to your funds.";
|
||||
strings_["wiz_passphrase"] = "Passphrase:";
|
||||
strings_["wiz_confirm"] = "Confirm:";
|
||||
strings_["wiz_strength_weak"] = "Weak";
|
||||
strings_["wiz_strength_fair"] = "Fair";
|
||||
strings_["wiz_strength_good"] = "Good";
|
||||
strings_["wiz_strength_strong"] = "Strong";
|
||||
strings_["wiz_strength"] = "Strength: %s";
|
||||
strings_["wiz_pass_too_short"] = "Passphrase must be at least 8 characters (%zu/8)";
|
||||
strings_["wiz_pass_mismatch"] = "Passphrases do not match";
|
||||
strings_["wiz_pass_spaces"] = "Passphrase has leading/trailing spaces \xe2\x80\x94 remove them";
|
||||
strings_["wiz_encrypt_continue"] = "Encrypt & Continue";
|
||||
strings_["wiz_encrypt_bg"] = "Encryption will complete in the background";
|
||||
strings_["wiz_skip_confirm"] = "Continue WITHOUT encryption? Keys will be stored unencrypted \xe2\x80\x94 click Skip again to confirm.";
|
||||
strings_["wiz_pin_optional"] = "Quick-Unlock PIN (optional)";
|
||||
strings_["wiz_pin_label"] = "PIN (4-8 digits):";
|
||||
strings_["wiz_pin_confirm"] = "Confirm PIN:";
|
||||
strings_["wiz_pin_invalid"] = "PIN must be 4-8 digits";
|
||||
strings_["wiz_pin_mismatch"] = "PINs do not match";
|
||||
strings_["settings_data_dir"] = "Data Dir:";
|
||||
strings_["settings_wallet_size_label"] = "Wallet Size:";
|
||||
strings_["settings_debug_changed"] = "Debug categories changed \xe2\x80\x94 restart daemon to apply";
|
||||
|
||||
Reference in New Issue
Block a user