diff --git a/res/fonts/NotoSansCJK-Subset.ttf b/res/fonts/NotoSansCJK-Subset.ttf index 7b393b0..1a753e4 100644 Binary files a/res/fonts/NotoSansCJK-Subset.ttf and b/res/fonts/NotoSansCJK-Subset.ttf differ diff --git a/res/lang/de.json b/res/lang/de.json index 3f3cc31..8e8e759 100644 --- a/res/lang/de.json +++ b/res/lang/de.json @@ -218,6 +218,9 @@ "console_welcome": "Willkommen bei ObsidianDragon Konsole", "console_zoom_in": "Vergrößern", "console_zoom_out": "Verkleinern", + "contact_global": "In jeder Wallet anzeigen (globaler Kontakt)", + "contact_global_badge_tt": "Globaler Kontakt — in jeder Wallet sichtbar", + "contact_global_tt": "Ein: Dieser Kontakt bleibt sichtbar, egal welche Wallet Sie laden. Aus: Er gehört nur zur aktuellen Wallet.", "copied": "Kopiert!", "copy": "Kopieren", "copy_address": "Vollständige Adresse kopieren", @@ -489,6 +492,7 @@ "mining_on": "Mining ist AN", "mining_open_in_explorer": "Im Explorer öffnen", "mining_payout_address": "Auszahlungsadresse", + "mining_payout_foreign": "⚠ Diese Auszahlungsadresse befindet sich nicht in Ihrer aktuellen Wallet — geschürfte Belohnungen würden an eine andere Wallet gehen. Aktualisieren Sie sie, wenn Sie die Wallet gewechselt haben.", "mining_payout_tooltip": "Adresse für Mining-Belohnungen", "mining_pool": "Pool", "mining_pool_hashrate": "Pool-Hashrate", @@ -967,6 +971,7 @@ "tt_ui_opacity": "Karten- und Seitenleisten-Deckkraft (100%% = vollständig undurchsichtig, niedriger = durchsichtiger)", "tt_validate": "Prüfen, ob eine DragonX-Adresse gültig ist", "tt_verbose": "Detaillierte Verbindungsdiagnosen,\\nDaemon-Status und Port-Besitzer-Info\\nin der Konsolen-Registerkarte protokollieren", + "tt_wallets_button": "Ihre Wallet-Dateien auflisten und zwischen ihnen wechseln", "tt_website": "Die DragonX-Website öffnen", "tt_window_opacity": "Hintergrund-Deckkraft (niedriger = Desktop durch Fenster sichtbar)", "tt_wizard": "Den Ersteinrichtungsassistenten erneut ausführen\\nDer Daemon wird neu gestartet", @@ -1012,6 +1017,33 @@ "wallet": "WALLET", "wallet_empty": "Ihre Wallet ist leer", "wallet_empty_hint": "Wechseln Sie zu Empfangen, um Ihre Adresse zu erhalten und Gelder zu empfangen.", + "wallets_active": "Aktiv", + "wallets_add": "Ordner hinzufügen", + "wallets_add_folder": "Auch einen weiteren Ordner nach Wallet-Dateien durchsuchen:", + "wallets_button": "Wallets…", + "wallets_col_addresses": "Adressen", + "wallets_col_balance": "Guthaben", + "wallets_col_name": "Wallet", + "wallets_col_opened": "Zuletzt geöffnet", + "wallets_col_size": "Größe", + "wallets_create": "Wallet erstellen", + "wallets_creating": "Wallet wird erstellt — der Node wird neu gestartet…", + "wallets_current": "aktuell", + "wallets_exists": "Eine Wallet mit diesem Namen existiert bereits.", + "wallets_folder_hint": "/pfad/zum/ordner mit .dat-Wallet-Dateien", + "wallets_folder_invalid": "Dieser Ordner existiert nicht.", + "wallets_import": "Importieren", + "wallets_import_failed": "Diese Wallet-Datei konnte nicht importiert werden.", + "wallets_import_hint": "Zum Öffnen importieren", + "wallets_import_tt": "Diese Wallet befindet sich außerhalb des Datenverzeichnisses. Beim Öffnen wird sie zuerst hineinkopiert (demnächst verfügbar).", + "wallets_imported": "Wallet importiert — wird gewechselt…", + "wallets_intro": "Wallet-Dateien in Ihrem Datenverzeichnis (und in beliebigen Ordnern, die Sie hinzufügen). Öffnen Sie eine, um zu wechseln — der Node wird neu gestartet, um sie zu laden, und jede Wallet behält ihre eigenen Daten.", + "wallets_name_invalid": "Bitte geben Sie einen gültigen Wallet-Namen ein.", + "wallets_never": "Nie", + "wallets_new_hint": "Name (z. B. Ersparnisse)", + "wallets_new_label": "Eine neue Wallet erstellen:", + "wallets_open": "Öffnen", + "wallets_title": "Wallets", "warning": "Warnung", "warning_upper": "WARNUNG!", "website": "Webseite", diff --git a/res/lang/es.json b/res/lang/es.json index 5270b8b..6945ac2 100644 --- a/res/lang/es.json +++ b/res/lang/es.json @@ -218,6 +218,9 @@ "console_welcome": "Bienvenido a la Consola de ObsidianDragon", "console_zoom_in": "Acercar", "console_zoom_out": "Alejar", + "contact_global": "Mostrar en todas las carteras (contacto global)", + "contact_global_badge_tt": "Contacto global — visible en todas las carteras", + "contact_global_tt": "Activado: este contacto permanece visible sin importar qué cartera cargues. Desactivado: pertenece solo a la cartera actual.", "copied": "¡Copiado!", "copy": "Copiar", "copy_address": "Copiar Dirección Completa", @@ -489,6 +492,7 @@ "mining_on": "La minería está ENCENDIDA", "mining_open_in_explorer": "Abrir en explorador", "mining_payout_address": "Dirección de Pago", + "mining_payout_foreign": "⚠ Esta dirección de pago no está en tu cartera actual — las recompensas minadas irían a otra cartera. Actualízala si cambiaste de cartera.", "mining_payout_tooltip": "Dirección para recibir recompensas de minería", "mining_pool": "Pool", "mining_pool_hashrate": "Hashrate del Pool", @@ -967,6 +971,7 @@ "tt_ui_opacity": "Opacidad de tarjetas y barra lateral (100%% = totalmente opaco, menor = más transparente)", "tt_validate": "Comprobar si una dirección DragonX es válida", "tt_verbose": "Registrar diagnósticos detallados de conexión,\\nestado del daemon e info de propietario de puerto\\nen la pestaña de Consola", + "tt_wallets_button": "Enumera tus archivos de cartera y cambia entre ellos", "tt_website": "Abrir el sitio web de DragonX", "tt_window_opacity": "Opacidad del fondo (menor = escritorio visible a través de la ventana)", "tt_wizard": "Volver a ejecutar el asistente de configuración inicial\\nEl daemon será reiniciado", @@ -1012,6 +1017,33 @@ "wallet": "CARTERA", "wallet_empty": "Tu cartera está vacía", "wallet_empty_hint": "Cambia a Recibir para obtener tu dirección y empezar a recibir fondos.", + "wallets_active": "Activa", + "wallets_add": "Agregar carpeta", + "wallets_add_folder": "Escanear también otra carpeta en busca de archivos de cartera:", + "wallets_button": "Carteras…", + "wallets_col_addresses": "Direcciones", + "wallets_col_balance": "Saldo", + "wallets_col_name": "Cartera", + "wallets_col_opened": "Última apertura", + "wallets_col_size": "Tamaño", + "wallets_create": "Crear cartera", + "wallets_creating": "Creando cartera — el nodo se reiniciará…", + "wallets_current": "actual", + "wallets_exists": "Ya existe una cartera con ese nombre.", + "wallets_folder_hint": "/ruta/a/carpeta con archivos .dat de cartera", + "wallets_folder_invalid": "Esa carpeta no existe.", + "wallets_import": "Importar", + "wallets_import_failed": "No se pudo importar ese archivo de cartera.", + "wallets_import_hint": "Importar para abrir", + "wallets_import_tt": "Esta cartera está fuera del directorio de datos. Al abrirla se copiará primero dentro (próximamente).", + "wallets_imported": "Cartera importada — cambiando…", + "wallets_intro": "Archivos de cartera en tu directorio de datos (y en las carpetas que agregues). Abre uno para cambiar: el nodo se reinicia para cargarlo y cada cartera conserva sus propios datos.", + "wallets_name_invalid": "Introduce un nombre de cartera válido.", + "wallets_never": "Nunca", + "wallets_new_hint": "Nombre (p. ej. ahorros)", + "wallets_new_label": "Crear una nueva cartera:", + "wallets_open": "Abrir", + "wallets_title": "Carteras", "warning": "Advertencia", "warning_upper": "¡ADVERTENCIA!", "website": "Sitio Web", diff --git a/res/lang/fr.json b/res/lang/fr.json index 2c47b03..d2c3ff1 100644 --- a/res/lang/fr.json +++ b/res/lang/fr.json @@ -218,6 +218,9 @@ "console_welcome": "Bienvenue dans la console ObsidianDragon", "console_zoom_in": "Agrandir", "console_zoom_out": "Réduire", + "contact_global": "Afficher dans tous les portefeuilles (contact global)", + "contact_global_badge_tt": "Contact global — visible dans tous les portefeuilles", + "contact_global_tt": "Activé : ce contact reste visible quel que soit le portefeuille chargé. Désactivé : il appartient au portefeuille actuel uniquement.", "copied": "Copié !", "copy": "Copier", "copy_address": "Copier l'adresse complète", @@ -489,6 +492,7 @@ "mining_on": "Le minage est ACTIVÉ", "mining_open_in_explorer": "Ouvrir dans l'explorateur", "mining_payout_address": "Adresse de paiement", + "mining_payout_foreign": "⚠ Cette adresse de paiement ne fait pas partie de votre portefeuille actuel — les récompenses minées iraient vers un autre portefeuille. Mettez-la à jour si vous avez changé de portefeuille.", "mining_payout_tooltip": "Adresse pour recevoir les récompenses de minage", "mining_pool": "Pool", "mining_pool_hashrate": "Hashrate du pool", @@ -967,6 +971,7 @@ "tt_ui_opacity": "Opacité des cartes et de la barre latérale (100%% = entièrement opaque, plus bas = plus transparent)", "tt_validate": "Vérifier si une adresse DragonX est valide", "tt_verbose": "Journaliser les diagnostics de connexion détaillés,\\nl'état du daemon et les informations de propriétaire de port\\ndans l'onglet Console", + "tt_wallets_button": "Répertoriez vos fichiers de portefeuille et passez de l'un à l'autre", "tt_website": "Ouvrir le site web DragonX", "tt_window_opacity": "Opacité de l'arrière-plan (plus bas = bureau visible à travers la fenêtre)", "tt_wizard": "Relancer l'assistant de configuration initiale\\nLe daemon sera redémarré", @@ -1012,6 +1017,33 @@ "wallet": "PORTEFEUILLE", "wallet_empty": "Votre portefeuille est vide", "wallet_empty_hint": "Passez à Recevoir pour obtenir votre adresse et commencer à recevoir des fonds.", + "wallets_active": "Actif", + "wallets_add": "Ajouter le dossier", + "wallets_add_folder": "Analyser aussi un autre dossier à la recherche de fichiers de portefeuille :", + "wallets_button": "Portefeuilles…", + "wallets_col_addresses": "Adresses", + "wallets_col_balance": "Solde", + "wallets_col_name": "Portefeuille", + "wallets_col_opened": "Dernière ouverture", + "wallets_col_size": "Taille", + "wallets_create": "Créer le portefeuille", + "wallets_creating": "Création du portefeuille — le nœud va redémarrer…", + "wallets_current": "actuel", + "wallets_exists": "Un portefeuille portant ce nom existe déjà.", + "wallets_folder_hint": "/chemin/vers/le/dossier contenant les fichiers .dat", + "wallets_folder_invalid": "Ce dossier n'existe pas.", + "wallets_import": "Importer", + "wallets_import_failed": "Impossible d'importer ce fichier de portefeuille.", + "wallets_import_hint": "Importer pour ouvrir", + "wallets_import_tt": "Ce portefeuille se trouve hors du répertoire de données. L'ouvrir le copiera d'abord dedans (bientôt disponible).", + "wallets_imported": "Portefeuille importé — changement en cours…", + "wallets_intro": "Fichiers de portefeuille dans votre répertoire de données (et tout dossier que vous ajoutez). Ouvrez-en un pour changer — le nœud redémarre pour le charger, et chaque portefeuille conserve ses propres données.", + "wallets_name_invalid": "Veuillez saisir un nom de portefeuille valide.", + "wallets_never": "Jamais", + "wallets_new_hint": "Nom (par ex. épargne)", + "wallets_new_label": "Créer un nouveau portefeuille :", + "wallets_open": "Ouvrir", + "wallets_title": "Portefeuilles", "warning": "Attention", "warning_upper": "ATTENTION !", "website": "Site web", diff --git a/res/lang/ja.json b/res/lang/ja.json index 43aad23..0b4dd42 100644 --- a/res/lang/ja.json +++ b/res/lang/ja.json @@ -218,6 +218,9 @@ "console_welcome": "ObsidianDragonコンソールへようこそ", "console_zoom_in": "拡大", "console_zoom_out": "縮小", + "contact_global": "すべてのウォレットで表示(グローバル連絡先)", + "contact_global_badge_tt": "グローバル連絡先 — すべてのウォレットで表示", + "contact_global_tt": "オン:この連絡先はどのウォレットを読み込んでも表示されます。オフ:現在のウォレットにのみ属します。", "copied": "コピーしました!", "copy": "コピー", "copy_address": "完全なアドレスをコピー", @@ -489,6 +492,7 @@ "mining_on": "マイニングはオンです", "mining_open_in_explorer": "エクスプローラーで開く", "mining_payout_address": "支払いアドレス", + "mining_payout_foreign": "⚠ この支払いアドレスは現在のウォレットに含まれていません — マイニング報酬が別のウォレットに送られます。ウォレットを切り替えた場合は更新してください。", "mining_payout_tooltip": "マイニング報酬の受取アドレス", "mining_pool": "プール", "mining_pool_hashrate": "プールハッシュレート", @@ -967,6 +971,7 @@ "tt_ui_opacity": "カードとサイドバーの不透明度(100%% = 完全不透明、低い = より透過)", "tt_validate": "DragonX アドレスが有効かどうかを確認", "tt_verbose": "詳細な接続診断、デーモン状態、\\nポート所有者情報をコンソールタブに記録", + "tt_wallets_button": "ウォレットファイルを一覧表示して切り替えます", "tt_website": "DragonX ウェブサイトを開く", "tt_window_opacity": "背景の不透明度(低い = デスクトップがウィンドウ越しに見える)", "tt_wizard": "初期セットアップウィザードを再実行\\nデーモンは再起動されます", @@ -1012,6 +1017,33 @@ "wallet": "ウォレット", "wallet_empty": "ウォレットは空です", "wallet_empty_hint": "受信に切り替えてアドレスを取得し、資金の受け取りを開始してください。", + "wallets_active": "アクティブ", + "wallets_add": "フォルダを追加", + "wallets_add_folder": "ウォレットファイルを検索する別のフォルダを追加:", + "wallets_button": "ウォレット…", + "wallets_col_addresses": "アドレス", + "wallets_col_balance": "残高", + "wallets_col_name": "ウォレット", + "wallets_col_opened": "最終使用", + "wallets_col_size": "サイズ", + "wallets_create": "ウォレットを作成", + "wallets_creating": "ウォレットを作成中 — ノードが再起動します…", + "wallets_current": "現在", + "wallets_exists": "その名前のウォレットは既に存在します。", + "wallets_folder_hint": "wallet .dat ファイルのあるフォルダのパス", + "wallets_folder_invalid": "そのフォルダは存在しません。", + "wallets_import": "インポート", + "wallets_import_failed": "そのウォレットファイルをインポートできませんでした。", + "wallets_import_hint": "インポートして開く", + "wallets_import_tt": "このウォレットはデータディレクトリの外にあります。開くには先にコピーが必要です(近日対応予定)。", + "wallets_imported": "ウォレットをインポートしました — 切り替え中…", + "wallets_intro": "データディレクトリ(および追加したフォルダ)内のウォレットファイルです。開いて切り替えると、それを読み込むためにノードが再起動します。各ウォレットは個別のデータを保持します。", + "wallets_name_invalid": "有効なウォレット名を入力してください。", + "wallets_never": "なし", + "wallets_new_hint": "名前(例:savings)", + "wallets_new_label": "新しいウォレットを作成:", + "wallets_open": "開く", + "wallets_title": "ウォレット", "warning": "警告", "warning_upper": "警告!", "website": "ウェブサイト", diff --git a/res/lang/ko.json b/res/lang/ko.json index 7e1e71a..cb0bb86 100644 --- a/res/lang/ko.json +++ b/res/lang/ko.json @@ -218,6 +218,9 @@ "console_welcome": "ObsidianDragon 콘솔에 오신 것을 환영합니다", "console_zoom_in": "확대", "console_zoom_out": "축소", + "contact_global": "모든 지갑에 표시(전역 연락처)", + "contact_global_badge_tt": "전역 연락처 — 모든 지갑에서 표시됨", + "contact_global_tt": "켜짐: 어떤 지갑을 불러오든 이 연락처가 계속 표시됩니다. 꺼짐: 현재 지갑에만 속합니다.", "copied": "복사됨!", "copy": "복사", "copy_address": "전체 주소 복사", @@ -489,6 +492,7 @@ "mining_on": "채굴이 켜져 있습니다", "mining_open_in_explorer": "탐색기에서 열기", "mining_payout_address": "지급 주소", + "mining_payout_foreign": "⚠ 이 지급 주소는 현재 지갑에 없습니다 — 채굴한 보상이 다른 지갑으로 전송됩니다. 지갑을 전환했다면 주소를 업데이트하세요.", "mining_payout_tooltip": "채굴 보상 수신 주소", "mining_pool": "풀", "mining_pool_hashrate": "풀 해시레이트", @@ -967,6 +971,7 @@ "tt_ui_opacity": "카드 및 사이드바 불투명도 (100%% = 완전 불투명, 낮을수록 더 투명)", "tt_validate": "DragonX 주소가 유효한지 확인", "tt_verbose": "콘솔 탭에 상세 연결 진단,\\n데몬 상태 및 포트 소유자 정보 기록", + "tt_wallets_button": "지갑 파일 목록을 보고 전환합니다", "tt_website": "DragonX 웹사이트 열기", "tt_window_opacity": "배경 불투명도 (낮을수록 = 창을 통해 바탕 화면이 보임)", "tt_wizard": "초기 설정 마법사 다시 실행\\n데몬이 재시작됩니다", @@ -1012,6 +1017,33 @@ "wallet": "지갑", "wallet_empty": "지갑이 비어 있습니다", "wallet_empty_hint": "수신으로 전환하여 주소를 받고 자금 수신을 시작하세요.", + "wallets_active": "활성", + "wallets_add": "폴더 추가", + "wallets_add_folder": "지갑 파일을 검색할 폴더를 추가로 지정:", + "wallets_button": "지갑…", + "wallets_col_addresses": "주소", + "wallets_col_balance": "잔액", + "wallets_col_name": "지갑", + "wallets_col_opened": "마지막 열람", + "wallets_col_size": "크기", + "wallets_create": "지갑 만들기", + "wallets_creating": "지갑을 만드는 중 — 노드가 재시작됩니다…", + "wallets_current": "현재", + "wallets_exists": "같은 이름의 지갑이 이미 존재합니다.", + "wallets_folder_hint": "wallet-*.dat 파일이 있는 폴더 경로", + "wallets_folder_invalid": "해당 폴더가 존재하지 않습니다.", + "wallets_import": "가져오기", + "wallets_import_failed": "해당 지갑 파일을 가져올 수 없습니다.", + "wallets_import_hint": "가져와서 열기", + "wallets_import_tt": "이 지갑은 데이터 디렉터리 밖에 있습니다. 열면 먼저 안으로 복사됩니다(출시 예정).", + "wallets_imported": "지갑을 가져왔습니다 — 전환 중…", + "wallets_intro": "데이터 디렉터리(및 추가한 폴더)에 있는 지갑 파일입니다. 하나를 열면 전환됩니다 — 노드가 재시작되어 해당 지갑을 불러오며, 각 지갑은 고유한 데이터를 유지합니다.", + "wallets_name_invalid": "유효한 지갑 이름을 입력하세요.", + "wallets_never": "없음", + "wallets_new_hint": "이름(예: savings)", + "wallets_new_label": "새 지갑 만들기:", + "wallets_open": "열기", + "wallets_title": "지갑", "warning": "경고", "warning_upper": "경고!", "website": "웹사이트", diff --git a/res/lang/pt.json b/res/lang/pt.json index ac9ab4f..6d857f1 100644 --- a/res/lang/pt.json +++ b/res/lang/pt.json @@ -218,6 +218,9 @@ "console_welcome": "Bem-vindo ao Console ObsidianDragon", "console_zoom_in": "Aumentar zoom", "console_zoom_out": "Diminuir zoom", + "contact_global": "Mostrar em todas as carteiras (contato global)", + "contact_global_badge_tt": "Contato global — visível em todas as carteiras", + "contact_global_tt": "Ativado: este contato permanece visível em qualquer carteira que você carregar. Desativado: ele pertence apenas à carteira atual.", "copied": "Copiado!", "copy": "Copiar", "copy_address": "Copiar Endereço Completo", @@ -489,6 +492,7 @@ "mining_on": "Mineração está LIGADA", "mining_open_in_explorer": "Abrir no explorador", "mining_payout_address": "Endereço de Pagamento", + "mining_payout_foreign": "⚠ Este endereço de pagamento não está na sua carteira atual — as recompensas mineradas iriam para uma carteira diferente. Atualize-o se você trocou de carteira.", "mining_payout_tooltip": "Endereço para receber recompensas de mineração", "mining_pool": "Pool", "mining_pool_hashrate": "Hashrate do Pool", @@ -967,6 +971,7 @@ "tt_ui_opacity": "Opacidade de cartões e barra lateral (100%% = totalmente opaco, menor = mais transparente)", "tt_validate": "Verificar se um endereço DragonX é válido", "tt_verbose": "Registrar diagnósticos detalhados de conexão,\\nestado do daemon e info de proprietário de porta\\nna aba Console", + "tt_wallets_button": "Liste os arquivos de carteira e alterne entre eles", "tt_website": "Abrir o site do DragonX", "tt_window_opacity": "Opacidade do fundo (menor = área de trabalho visível através da janela)", "tt_wizard": "Executar novamente o assistente de configuração inicial\\nO daemon será reiniciado", @@ -1012,6 +1017,33 @@ "wallet": "CARTEIRA", "wallet_empty": "Sua carteira está vazia", "wallet_empty_hint": "Mude para Receber para obter seu endereço e começar a receber fundos.", + "wallets_active": "Ativa", + "wallets_add": "Adicionar pasta", + "wallets_add_folder": "Verificar também outra pasta em busca de arquivos de carteira:", + "wallets_button": "Carteiras…", + "wallets_col_addresses": "Endereços", + "wallets_col_balance": "Saldo", + "wallets_col_name": "Carteira", + "wallets_col_opened": "Aberta pela última vez", + "wallets_col_size": "Tamanho", + "wallets_create": "Criar carteira", + "wallets_creating": "Criando carteira — o nó será reiniciado…", + "wallets_current": "atual", + "wallets_exists": "Já existe uma carteira com esse nome.", + "wallets_folder_hint": "/caminho/para/pasta com arquivos .dat de carteira", + "wallets_folder_invalid": "Essa pasta não existe.", + "wallets_import": "Importar", + "wallets_import_failed": "Não foi possível importar esse arquivo de carteira.", + "wallets_import_hint": "Importar para abrir", + "wallets_import_tt": "Esta carteira está fora do diretório de dados. Ao abri-la, ela será copiada para lá primeiro (em breve).", + "wallets_imported": "Carteira importada — alternando…", + "wallets_intro": "Arquivos de carteira no seu diretório de dados (e em quaisquer pastas que você adicionar). Abra um para alternar — o nó reinicia para carregá-lo, e cada carteira mantém seus próprios dados.", + "wallets_name_invalid": "Insira um nome de carteira válido.", + "wallets_never": "Nunca", + "wallets_new_hint": "Nome (ex.: poupança)", + "wallets_new_label": "Criar uma nova carteira:", + "wallets_open": "Abrir", + "wallets_title": "Carteiras", "warning": "Aviso", "warning_upper": "AVISO!", "website": "Website", diff --git a/res/lang/ru.json b/res/lang/ru.json index 8009552..6d08e6f 100644 --- a/res/lang/ru.json +++ b/res/lang/ru.json @@ -218,6 +218,9 @@ "console_welcome": "Добро пожаловать в консоль ObsidianDragon", "console_zoom_in": "Увеличить", "console_zoom_out": "Уменьшить", + "contact_global": "Показывать во всех кошельках (глобальный контакт)", + "contact_global_badge_tt": "Глобальный контакт — виден во всех кошельках", + "contact_global_tt": "Вкл.: этот контакт остаётся видимым, какой бы кошелёк вы ни загрузили. Выкл.: он принадлежит только текущему кошельку.", "copied": "Скопировано!", "copy": "Копировать", "copy_address": "Копировать полный адрес", @@ -489,6 +492,7 @@ "mining_on": "Майнинг ВКЛЮЧЁН", "mining_open_in_explorer": "Открыть в обозревателе", "mining_payout_address": "Адрес выплат", + "mining_payout_foreign": "⚠ Этот адрес выплат отсутствует в вашем текущем кошельке — намайненные вознаграждения будут отправлены в другой кошелёк. Обновите его, если вы сменили кошелёк.", "mining_payout_tooltip": "Адрес для получения вознаграждений за майнинг", "mining_pool": "Пул", "mining_pool_hashrate": "Хешрейт пула", @@ -967,6 +971,7 @@ "tt_ui_opacity": "Непрозрачность карточек и боковой панели (100%% = полностью непрозрачно, ниже = прозрачнее)", "tt_validate": "Проверить, действителен ли адрес DragonX", "tt_verbose": "Записывать подробную диагностику подключений,\\nсостояние демона и информацию о владельце порта\\nна вкладке Консоль", + "tt_wallets_button": "Показать файлы кошельков и переключаться между ними", "tt_website": "Открыть сайт DragonX", "tt_window_opacity": "Непрозрачность фона (ниже = рабочий стол виден сквозь окно)", "tt_wizard": "Повторно запустить мастер начальной настройки\\nДемон будет перезапущен", @@ -1012,6 +1017,33 @@ "wallet": "КОШЕЛЁК", "wallet_empty": "Ваш кошелёк пуст", "wallet_empty_hint": "Перейдите к получению, чтобы получить свой адрес и начать получать средства.", + "wallets_active": "Активен", + "wallets_add": "Добавить папку", + "wallets_add_folder": "Также сканировать другую папку на наличие файлов кошельков:", + "wallets_button": "Кошельки…", + "wallets_col_addresses": "Адреса", + "wallets_col_balance": "Баланс", + "wallets_col_name": "Кошелёк", + "wallets_col_opened": "Последнее открытие", + "wallets_col_size": "Размер", + "wallets_create": "Создать кошелёк", + "wallets_creating": "Создание кошелька — узел будет перезапущен…", + "wallets_current": "текущий", + "wallets_exists": "Кошелёк с таким именем уже существует.", + "wallets_folder_hint": "/путь/к/папке с файлами кошельков .dat", + "wallets_folder_invalid": "Такой папки не существует.", + "wallets_import": "Импорт", + "wallets_import_failed": "Не удалось импортировать этот файл кошелька.", + "wallets_import_hint": "Импортировать для открытия", + "wallets_import_tt": "Этот кошелёк находится вне папки данных. При открытии он сначала будет скопирован в неё (скоро).", + "wallets_imported": "Кошелёк импортирован — переключение…", + "wallets_intro": "Файлы кошельков в вашей папке данных (и в любых добавленных вами папках). Откройте один, чтобы переключиться — узел перезапустится, чтобы загрузить его, и у каждого кошелька свои данные.", + "wallets_name_invalid": "Введите допустимое имя кошелька.", + "wallets_never": "Никогда", + "wallets_new_hint": "Имя (например, savings)", + "wallets_new_label": "Создать новый кошелёк:", + "wallets_open": "Открыть", + "wallets_title": "Кошельки", "warning": "Предупреждение", "warning_upper": "ПРЕДУПРЕЖДЕНИЕ!", "website": "Веб-сайт", diff --git a/res/lang/zh.json b/res/lang/zh.json index 03b03b4..f2dede6 100644 --- a/res/lang/zh.json +++ b/res/lang/zh.json @@ -218,6 +218,9 @@ "console_welcome": "欢迎使用 ObsidianDragon 控制台", "console_zoom_in": "放大", "console_zoom_out": "缩小", + "contact_global": "在每个钱包中显示(全局联系人)", + "contact_global_badge_tt": "全局联系人——在每个钱包中可见", + "contact_global_tt": "开启:无论您加载哪个钱包,此联系人都保持可见。关闭:它仅属于当前钱包。", "copied": "已复制!", "copy": "复制", "copy_address": "复制完整地址", @@ -489,6 +492,7 @@ "mining_on": "挖矿已开启", "mining_open_in_explorer": "在浏览器中打开", "mining_payout_address": "支付地址", + "mining_payout_foreign": "⚠ 此支付地址不在您当前的钱包中——挖矿奖励将进入另一个钱包。如果您切换过钱包,请更新它。", "mining_payout_tooltip": "接收挖矿奖励的地址", "mining_pool": "矿池", "mining_pool_hashrate": "矿池算力", @@ -967,6 +971,7 @@ "tt_ui_opacity": "卡片和侧边栏不透明度(100%% = 完全不透明,越低越透明)", "tt_validate": "检查 DragonX 地址是否有效", "tt_verbose": "将详细连接诊断、守护进程状态\\n和端口所有者信息记录到控制台选项卡", + "tt_wallets_button": "列出您的钱包文件并在它们之间切换", "tt_website": "打开 DragonX 网站", "tt_window_opacity": "背景不透明度(越低 = 桌面透过窗口可见)", "tt_wizard": "重新运行初始设置向导\\n守护进程将被重启", @@ -1012,6 +1017,33 @@ "wallet": "钱包", "wallet_empty": "您的钱包是空的", "wallet_empty_hint": "切换到接收页面获取您的地址并开始接收资金。", + "wallets_active": "活跃", + "wallets_add": "添加文件夹", + "wallets_add_folder": "同时扫描另一个文件夹中的钱包文件:", + "wallets_button": "钱包…", + "wallets_col_addresses": "地址", + "wallets_col_balance": "余额", + "wallets_col_name": "钱包", + "wallets_col_opened": "上次打开", + "wallets_col_size": "大小", + "wallets_create": "创建钱包", + "wallets_creating": "正在创建钱包——节点将重启…", + "wallets_current": "当前", + "wallets_exists": "已存在同名钱包。", + "wallets_folder_hint": "/含 .dat 钱包文件的文件夹路径", + "wallets_folder_invalid": "该文件夹不存在。", + "wallets_import": "导入", + "wallets_import_failed": "无法导入该钱包文件。", + "wallets_import_hint": "导入以打开", + "wallets_import_tt": "此钱包位于数据目录之外。打开它会先将其复制进来(即将推出)。", + "wallets_imported": "钱包已导入——正在切换…", + "wallets_intro": "位于您数据目录(以及您添加的任何文件夹)中的钱包文件。打开一个即可切换——节点将重启以加载它,且每个钱包各自保留其数据。", + "wallets_name_invalid": "请输入有效的钱包名称。", + "wallets_never": "从未", + "wallets_new_hint": "名称(例如 savings)", + "wallets_new_label": "创建新钱包:", + "wallets_open": "打开", + "wallets_title": "钱包", "warning": "警告", "warning_upper": "警告!", "website": "网站", diff --git a/src/app_sweep.cpp b/src/app_sweep.cpp index 882a6cd..697ef50 100644 --- a/src/app_sweep.cpp +++ b/src/app_sweep.cpp @@ -282,6 +282,12 @@ void App::buildSweepCatalog() e2.lastOpenedEpoch = 1719400000; e2.syncedHere = true; a.walletIndex().upsert(e1); a.walletIndex().upsert(e2); + // An out-of-datadir wallet (in an extra folder) so the Import action shows too. + const std::string extra = util::Platform::getConfigDir() + "extra-wallets"; + fs::create_directories(extra, ec); + if (!fs::exists(extra + "/my-wallet.dat", ec)) + std::ofstream(extra + "/my-wallet.dat", std::ios::binary) << std::string(80000, '\0'); + a.walletIndex().addExtraFolder(extra); if (a.settings()) a.settings()->setActiveWalletFile("wallet.dat"); ui::WalletsDialog::show(&a); }, diff --git a/src/ui/windows/wallets_dialog.h b/src/ui/windows/wallets_dialog.h index 6ff5de7..6785ea5 100644 --- a/src/ui/windows/wallets_dialog.h +++ b/src/ui/windows/wallets_dialog.h @@ -9,6 +9,7 @@ #pragma once +#include #include #include #include @@ -120,9 +121,10 @@ public: s_open = false; // node restarts; the main UI shows the reconnect overlay } } else { - // Out-of-datadir wallets can't be loaded directly (the daemon rejects paths); - // opening one means importing (copy into the datadir) — a P3 action. - ImGui::TextDisabled("%s", TR("wallets_import_hint")); + // Out-of-datadir wallets can't be loaded directly (the daemon rejects paths). + // Import = copy into the datadir under a wallet-*.dat name, then switch to it. + if (StyledButton(TR("wallets_import"), ImVec2(90.0f * dp, 0))) + importAndOpen(app, r); if (ImGui::IsItemHovered()) Tooltip("%s", TR("wallets_import_tt")); } ImGui::PopID(); @@ -132,6 +134,28 @@ public: ImGui::Dummy(ImVec2(0, Layout::spacingSm())); + // Create a fresh named wallet — the daemon mints it (with a seed phrase) on first load. + Type().textColored(TypeStyle::Caption, OnSurfaceMedium(), TR("wallets_new_label")); + ImGui::SetNextItemWidth(-150.0f * dp); + ImGui::InputTextWithHint("##newWalletName", TR("wallets_new_hint"), s_newName, sizeof(s_newName)); + ImGui::SameLine(); + if (StyledButton(TR("wallets_create"), ImVec2(120.0f * dp, 0))) { + std::string name = normalizeWalletName(s_newName); + std::error_code ec; + if (name.empty()) { + Notifications::instance().warning(TR("wallets_name_invalid")); + } else if (std::filesystem::exists(util::Platform::getDragonXDataDir() + "/" + name, ec)) { + Notifications::instance().warning(TR("wallets_exists")); + } else { + s_newName[0] = '\0'; + Notifications::instance().info(TR("wallets_creating")); + app->switchToWallet(name); // daemon creates it on start (-usemnemonic=1 -> seed-backed) + s_open = false; + } + } + + ImGui::Dummy(ImVec2(0, Layout::spacingSm())); + // Add a folder to also scan for wallet files (no native picker — a validated path input). Type().textColored(TypeStyle::Caption, OnSurfaceMedium(), TR("wallets_add_folder")); ImGui::SetNextItemWidth(-150.0f * dp); @@ -167,6 +191,42 @@ private: long long sizeBytes = 0; }; + // Force a "wallet-...dat" filename (plain, no path) so a new/imported wallet shows in the + // datadir scan and can't collide with the daemon's internal .dat files. Returns "" if the + // input has no usable characters. + static std::string normalizeWalletName(const std::string& raw) { + std::string s = raw; + while (!s.empty() && static_cast(s.front()) <= ' ') s.erase(s.begin()); + while (!s.empty() && static_cast(s.back()) <= ' ') s.pop_back(); + auto slash = s.find_last_of("/\\"); + if (slash != std::string::npos) s = s.substr(slash + 1); + if (s.size() > 4 && s.substr(s.size() - 4) == ".dat") s = s.substr(0, s.size() - 4); + std::string clean; + for (char c : s) + if (std::isalnum(static_cast(c)) || c == '-' || c == '_') clean += c; + if (clean.empty()) return ""; + if (clean.rfind("wallet", 0) != 0) clean = "wallet-" + clean; + return clean + ".dat"; + } + + // Copy an out-of-datadir wallet file into the datadir (the daemon only loads plain filenames + // from there) under a wallet-*.dat name, then switch to it. Never overwrites an existing file. + static void importAndOpen(App* app, const WalletRow& r) { + namespace fs = std::filesystem; + std::string dest = normalizeWalletName(r.fileName); + if (dest.empty()) { Notifications::instance().warning(TR("wallets_name_invalid")); return; } + std::error_code ec; + const std::string datadir = util::Platform::getDragonXDataDir(); + fs::create_directories(datadir, ec); + const std::string destPath = datadir + "/" + dest; + if (fs::exists(destPath, ec)) { Notifications::instance().warning(TR("wallets_exists")); return; } + fs::copy_file(r.dir + "/" + r.fileName, destPath, ec); + if (ec) { Notifications::instance().error(TR("wallets_import_failed")); return; } + Notifications::instance().success(TR("wallets_imported")); + app->switchToWallet(dest); + s_open = false; + } + // Scan the datadir (wallet-prefixed *.dat only, to skip peers.dat / asmap.dat / fee_estimates.dat) // and each user-added folder (any *.dat). Exception-safe: iterates with error_codes. static void scan() { @@ -200,6 +260,7 @@ private: static inline App* s_app = nullptr; static inline bool s_needScan = false; static inline char s_newFolder[512] = ""; + static inline char s_newName[128] = ""; static inline std::vector s_rows; }; diff --git a/src/util/i18n.cpp b/src/util/i18n.cpp index bc62a8b..905ad6c 100644 --- a/src/util/i18n.cpp +++ b/src/util/i18n.cpp @@ -270,6 +270,15 @@ void I18n::loadBuiltinEnglish() strings_["wallets_folder_hint"] = "/path/to/folder with wallet .dat files"; strings_["wallets_add"] = "Add folder"; strings_["wallets_folder_invalid"] = "That folder doesn't exist."; + strings_["wallets_import"] = "Import"; + strings_["wallets_new_label"] = "Create a new wallet:"; + strings_["wallets_new_hint"] = "Name (e.g. savings)"; + strings_["wallets_create"] = "Create wallet"; + strings_["wallets_name_invalid"] = "Please enter a valid wallet name."; + strings_["wallets_exists"] = "A wallet with that name already exists."; + strings_["wallets_imported"] = "Wallet imported — switching…"; + strings_["wallets_import_failed"] = "Could not import that wallet file."; + strings_["wallets_creating"] = "Creating wallet — the node will restart…"; strings_["tt_seed_migrate"] = "Create a new seed-phrase wallet and move your funds into it"; // Migrate-to-seed modal strings_["mig_title"] = "Migrate to a seed wallet";