docs: translate all code comments to English (language policy)

Translate every Italian /// XML doc comment, <!-- --> XAML comment, and
// inline comment to English across all source files (Core, App, tests).
Add the language policy to CLAUDE.md (conversation Italian; all code
and docs English). Update one test assertion that checked an Italian
exception message that was also translated.
This commit is contained in:
2026-06-16 14:40:06 +02:00
parent 4b82a0852c
commit 3d5a226a5a
59 changed files with 721 additions and 716 deletions
@@ -6,8 +6,8 @@ using Avalonia.Data.Converters;
namespace PalladiumWallet.App.ViewModels;
/// <summary>
/// true (mobile) → Dock.Bottom — tab strip in basso, standard Android.
/// false (desktop) → Dock.Top — comportamento predefinito Avalonia.
/// true (mobile) → Dock.Bottom — tab strip at the bottom, Android standard.
/// false (desktop) → Dock.Top — Avalonia default behavior.
/// </summary>
public sealed class BoolToTabPlacementConverter : IValueConverter
{
@@ -13,7 +13,7 @@ public partial class MainWindowViewModel
[ObservableProperty]
private ContactEntry? selectedContactInList;
/// <summary>Contatto selezionato nella ComboBox del pannello Invia: riempie SendTo.</summary>
/// <summary>Contact selected in the Send panel's ComboBox: fills SendTo.</summary>
[ObservableProperty]
private ContactEntry? sendToContact;
@@ -17,7 +17,7 @@ namespace PalladiumWallet.App.ViewModels;
public partial class MainWindowViewModel
{
// ---- saldo e info wallet ----
// ---- balance and wallet info ----
[ObservableProperty]
private string balanceText = "—";
@@ -28,7 +28,7 @@ public partial class MainWindowViewModel
[ObservableProperty]
private string networkInfo = "";
// ---- indirizzo di ricezione e QR ----
// ---- receive address and QR ----
[ObservableProperty]
private string receiveAddress = "";
@@ -60,7 +60,7 @@ public partial class MainWindowViewModel
}
}
// ---- tab indirizzi ----
// ---- addresses tab ----
[ObservableProperty]
private AddressRow? selectedAddressRow;
@@ -74,7 +74,7 @@ public partial class MainWindowViewModel
[RelayCommand]
private void CloseAddressInfo() => AddressInfo = null;
// ---- overlay dettaglio transazione ----
// ---- transaction detail overlay ----
[ObservableProperty]
private bool isTxDetailsOpen;
@@ -169,7 +169,7 @@ public partial class MainWindowViewModel
}
}
// ---- aggiorna display dal risultato della sync ----
// ---- update display from the sync result ----
private void ApplyCache(SyncCache? cache)
{
@@ -36,7 +36,7 @@ public partial class MainWindowViewModel
if (PlatformServices.ScanQrAsync is not { } scan) return;
var raw = await scan();
if (string.IsNullOrWhiteSpace(raw)) return;
// Gestisce URI tipo "palladium:ADDRESS?amount=X" estraendo solo l'indirizzo
// Handle URIs like "palladium:ADDRESS?amount=X" — extract address only
var address = raw.Contains(':') ? raw.Split(':')[1] : raw;
if (address.Contains('?')) address = address.Split('?')[0];
SendTo = address.Trim();
+19 -19
View File
@@ -16,7 +16,7 @@ namespace PalladiumWallet.App.ViewModels;
public partial class MainWindowViewModel
{
// ---- server e connessione ----
// ---- server and connection ----
[ObservableProperty]
private string serverHost = "";
@@ -118,20 +118,20 @@ public partial class MainWindowViewModel
}
/// <summary>
/// Restituisce i server da provare in ordine: prima quello selezionato nella UI
/// (o digitato manualmente), poi gli altri in KnownServers, evitando duplicati.
/// Returns servers to try in order: first the one selected in the UI
/// (or manually typed), then the remaining KnownServers, with duplicates skipped.
/// </summary>
private IEnumerable<(string Host, int Port)> BuildServerCandidates(string selectedHost, int selectedPort)
{
var seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
// 1. Server corrente (selezionato o digitato manualmente).
// 1. Current server (selected or manually typed).
if (!string.IsNullOrWhiteSpace(selectedHost))
{
var key = $"{selectedHost}:{selectedPort}";
if (seen.Add(key))
yield return (selectedHost, selectedPort);
}
// 2. Altri server noti, in ordine di lista.
// 2. Other known servers, in list order.
foreach (var s in KnownServers)
{
var p = s.PortFor(UseSsl);
@@ -163,14 +163,14 @@ public partial class MainWindowViewModel
if (_client is null || !_client.IsConnected)
{
// Salva le cache prima di distruggere il synchronizer: il nuovo
// synchronizer userà un client diverso e deve essere ricreato,
// ma i dati già scaricati vengono preservati via _doc.Cache.
// Persist caches before destroying the synchronizer: the new
// synchronizer will use a different client and must be recreated,
// but already-downloaded data is preserved via _doc.Cache.
PersistPartialTxCache();
_synchronizer = null;
// Prova tutti i server noti in ordine; parte da quello selezionato
// e scorre la lista fino al primo che risponde.
// Try all known servers in order; starts with the selected one
// and walks the list until the first that responds.
var candidates = BuildServerCandidates(host, port);
Exception? lastError = null;
foreach (var (h, p) in candidates)
@@ -189,7 +189,7 @@ public partial class MainWindowViewModel
IsConnected = true;
_autoReconnect = true;
ConnectionStatus = Loc.Tr("conn.connectedto");
// Aggiorna la UI per riflettere il server effettivamente connesso.
// Update the UI to reflect the server actually connected.
_syncingServerFields = true;
ServerHost = h;
ServerPort = p.ToString();
@@ -215,8 +215,8 @@ public partial class MainWindowViewModel
if (_synchronizer is null)
{
_synchronizer = new WalletSynchronizer(_account, _client!, _doc.GapLimit);
// Ricarica dalla cache su disco: evita di riscaricale le tx già note
// (fondamentale per wallet con migliaia di tx storiche — previene -101).
// Reload from disk cache: avoids re-downloading already known transactions
// (essential for wallets with thousands of historical txs — prevents -101).
var net = PalladiumNetworks.For(_account.Profile.Kind);
_synchronizer.PreloadCaches(
_doc.Cache?.RawTxHex ?? [],
@@ -271,8 +271,8 @@ public partial class MainWindowViewModel
if (_account is not null)
{
_syncFailed = true;
// Salva le tx già scaricate: al retry il synchronizer riparte
// da qui invece di ricominciare da zero (es. dopo -101).
// Persist already-downloaded transactions: on retry the synchronizer
// resumes from here instead of starting from scratch (e.g. after -101).
PersistPartialTxCache();
}
}
@@ -327,9 +327,9 @@ public partial class MainWindowViewModel
}
/// <summary>
/// Salva nel SyncCache le tx e le prove di Merkle già accumulate dal synchronizer,
/// anche se la sync non è ancora completa. Consente al retry successivo
/// (o al riavvio dell'app) di riprendere senza riscaricale da zero.
/// Persists the transactions and Merkle proofs already accumulated by the synchronizer
/// into SyncCache, even if sync is not yet complete. Allows the next retry
/// (or app restart) to resume without re-downloading from scratch.
/// </summary>
private void PersistPartialTxCache()
{
@@ -346,7 +346,7 @@ public partial class MainWindowViewModel
_doc.Cache.BlockHeaders = blockHeaders;
WalletStore.Save(_doc, _walletPath, _password);
}
catch { /* non fatale: il prossimo salvataggio completo recupererà */ }
catch { /* non-fatal: the next full save will recover */ }
}
private async Task DisconnectAsync()
@@ -14,7 +14,7 @@ namespace PalladiumWallet.App.ViewModels;
public partial class MainWindowViewModel
{
// ---- wizard di setup
// ---- setup wizard
public const string StepDataLocation = "data-location";
public const string StepStart = "start";
@@ -85,7 +85,7 @@ public partial class MainWindowViewModel
[ObservableProperty]
private string importWifInput = "";
// Tipo di script rilevato durante la decodifica dell'xkey (per mostrarlo all'utente)
// Script type detected during xkey decoding (to display to the user)
[ObservableProperty]
private string importXkeyDetectedKind = "";
@@ -268,7 +268,7 @@ public partial class MainWindowViewModel
StatusMessage = Loc.Tr("msg.xkey.required");
return;
}
// Valida e rileva il tipo: prova prima come xpub, poi come xprv.
// Validate and detect the type: try as xpub first, then as xprv.
if (Slip132.TryDecodePublic(ImportXkeyInput.Trim(), Profile, out _, out var pubKind))
{
SelectedScriptKind = pubKind;
@@ -298,7 +298,7 @@ public partial class MainWindowViewModel
StatusMessage = Loc.Tr("msg.wif.required");
return;
}
// Valida il WIF con un parsing anticipato.
// Validate the WIF with an early parse.
try
{
_ = new NBitcoin.BitcoinSecret(ImportWifInput.Trim(), PalladiumNetworks.For(Net));
@@ -421,9 +421,9 @@ public partial class MainWindowViewModel
}
/// <summary>
/// Costruisce il percorso file dal nome inserito dall'utente.
/// Se il nome è vuoto genera un nome automatico (default, wallet-2, …).
/// Rimuove i caratteri non validi per il filesystem.
/// Builds the file path from the name entered by the user.
/// If the name is empty, generates an automatic name (default, wallet-2, …).
/// Removes characters that are invalid for the filesystem.
/// </summary>
private string WalletPathFromName(string name)
{
@@ -435,7 +435,7 @@ public partial class MainWindowViewModel
if (string.IsNullOrEmpty(clean))
{
// Nessun nome → nome automatico
// No name provided → auto-generated name
var def = AppPaths.DefaultWalletPath(Net);
for (var n = 2; WalletStore.Exists(def); n++)
def = Path.Combine(AppPaths.WalletsDir(Net), $"wallet-{n}.wallet.json");
@@ -547,8 +547,8 @@ public partial class MainWindowViewModel
ApplyCache(doc.Cache);
IsWalletOpen = true;
StatusMessage = Loc.Tr("msg.opened");
_autoReconnect = true; // keepalive riprova la connessione anche se il primo tentativo fallisce
_syncFailed = true; // forza la prima sync automatica
_autoReconnect = true; // keepalive retries the connection even if the first attempt fails
_syncFailed = true; // force the first automatic sync
_ = ConnectAndSync();
}
}
+19 -19
View File
@@ -16,10 +16,10 @@ using PalladiumWallet.Core.Wallet;
namespace PalladiumWallet.App.ViewModels;
/// <summary>Riga dello storico transazioni per la vista.</summary>
/// <summary>Transaction history row for the view.</summary>
public sealed record HistoryRow(string Conferma, string Importo, string Txid, string Verificata);
/// <summary>Riga della vista indirizzi con chiavi e derivation path pre-calcolati.</summary>
/// <summary>Address view row with pre-computed keys and derivation path.</summary>
public sealed record AddressRow(
string Tipo, int Indice, string Indirizzo, string Saldo, string NumTx,
bool IsChange = false, string PubKey = "", string PrivKey = "", string DerivPath = "")
@@ -27,7 +27,7 @@ public sealed record AddressRow(
public bool HasPrivKey => !string.IsNullOrEmpty(PrivKey);
}
/// <summary>Dati completi di un indirizzo passati alla finestra di dettaglio.</summary>
/// <summary>Full address data passed to the address detail overlay.</summary>
public sealed record AddressInfo(
Loc Loc,
string Address, string DerivPath, string PubKey, string PrivKey)
@@ -35,38 +35,38 @@ public sealed record AddressInfo(
public bool HasPrivKey => !string.IsNullOrEmpty(PrivKey);
}
/// <summary>Contatto in rubrica: nome + indirizzo blockchain.</summary>
/// <summary>Address book contact: name + blockchain address.</summary>
public sealed record ContactEntry(string Name, string Address);
/// <summary>Voce della lista di scelta wallet: nome file + percorso completo.</summary>
/// <summary>Wallet list entry: display name + full file path.</summary>
public sealed record WalletFileEntry(string Name, string Path);
/// <summary>
/// ViewModel unico dell'applicazione (wizard + dashboard). Suddiviso in file
/// partial per area: Wizard, Settings, Sync, Send, Contacts, Receive.
/// Single application ViewModel (wizard + dashboard). Split into partial files
/// by area: Wizard, Settings, Sync, Send, Contacts, Receive.
/// </summary>
public partial class MainWindowViewModel : ViewModelBase
{
// ---- stato sessione wallet ----
// ---- wallet session state ----
private WalletDocument? _doc;
private IWalletAccount? _account;
private string? _walletPath;
private string? _password;
private WalletLock? _walletLock;
// ---- rete ----
// ---- network ----
private ElectrumClient? _client;
private WalletSynchronizer? _synchronizer;
private IReadOnlyDictionary<string, Transaction>? _lastTransactions;
private bool _resyncRequested;
// ---- invio ----
// ---- send ----
private BuiltTransaction? _pendingSend;
// ---- dettaglio transazione ----
// ---- transaction detail ----
private CancellationTokenSource? _txDetailsCts;
// ---- configurazione e localizzazione ----
// ---- configuration and localisation ----
private AppConfig _config = AppConfig.Load();
private Loc _loc = Loc.Instance;
public Loc Loc => _loc;
@@ -82,7 +82,7 @@ public partial class MainWindowViewModel : ViewModelBase
// ---- server UI sync ----
private bool _syncingServerFields;
// ---- proprietà di app ----
// ---- app properties ----
public static string AppVersion =>
typeof(MainWindowViewModel).Assembly.GetName().Version is { } v
@@ -91,7 +91,7 @@ public partial class MainWindowViewModel : ViewModelBase
public string WindowTitle => $"Palladium Wallet {AppVersion}";
/// <summary>true su desktop; false su Android/iOS — nasconde le funzioni legate al filesystem libero.</summary>
/// <summary>True on desktop; false on Android/iOS — hides filesystem-dependent features.</summary>
public bool IsDesktop => !OperatingSystem.IsAndroid() && !OperatingSystem.IsIOS();
public bool IsMobile => !IsDesktop;
@@ -99,7 +99,7 @@ public partial class MainWindowViewModel : ViewModelBase
public string UnitLabel => _config.Unit;
public AppConfig CurrentConfig => _config;
// ---- stato pannelli ----
// ---- panel state ----
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(IsSetupVisible))]
@@ -116,7 +116,7 @@ public partial class MainWindowViewModel : ViewModelBase
[RelayCommand]
private void SelectTab(string index) => SelectedTabIndex = int.Parse(index);
// ---- collections per la dashboard ----
// ---- dashboard collections ----
public ObservableCollection<HistoryRow> History { get; } = [];
public ObservableCollection<AddressRow> Addresses { get; } = [];
@@ -141,7 +141,7 @@ public partial class MainWindowViewModel : ViewModelBase
catch { return ""; }
}
// ---- costruttore ----
// ---- constructor ----
public MainWindowViewModel()
{
@@ -161,7 +161,7 @@ public partial class MainWindowViewModel : ViewModelBase
return;
if (_client is { IsConnected: true })
{
// Se il wallet è aperto e l'ultima sync è fallita, riprova automaticamente.
// If the wallet is open and the last sync failed, retry automatically.
if (_syncFailed && _account is not null)
{
await ConnectAndSync();
@@ -177,7 +177,7 @@ public partial class MainWindowViewModel : ViewModelBase
}
}
// ---- ciclo di vita wallet ----
// ---- wallet lifecycle ----
[RelayCommand]
private void CloseWallet()
+2 -2
View File
@@ -7,8 +7,8 @@ using Avalonia.Media;
namespace PalladiumWallet.App.ViewModels;
/// <summary>
/// bool → pennello: gli indirizzi del wallet (input/output "nostri") sono
/// evidenziati in verde, gli altri usano il colore di testo predefinito.
/// bool → brush: the wallet's own addresses ("our" inputs/outputs) are
/// highlighted in green, the others use the default text color.
/// </summary>
public sealed class MineColorConverter : IValueConverter
{
@@ -7,13 +7,13 @@ using PalladiumWallet.Core.Wallet;
namespace PalladiumWallet.App.ViewModels;
/// <summary>Riga input/output per le tabelle della finestra di dettaglio.</summary>
/// <summary>Input/output row for the transaction detail tables.</summary>
public sealed record TxIoRow(string Position, string Address, string Amount, bool IsMine);
/// <summary>
/// ViewModel della finestra di dettaglio transazione: prende un
/// <see cref="TransactionDetails"/> (assemblato dal server) e ne ricava tutte
/// le stringhe già formattate e localizzate per la vista. È di sola lettura.
/// ViewModel for the transaction detail view: takes a
/// <see cref="TransactionDetails"/> (assembled from server data) and produces
/// all strings already formatted and localised for the view. Read-only.
/// </summary>
public sealed class TransactionDetailsViewModel
{
@@ -35,14 +35,14 @@ public sealed class TransactionDetailsViewModel
var counterparties = d.CounterpartyAddresses;
CounterpartyHeader = d.IsIncoming ? loc["tx.from"] : loc["tx.to"];
// Una coinbase non ha mittente: le monete sono generate dal mining.
// Coinbase has no sender: coins are newly generated by mining.
CounterpartyText = d.IsCoinbase
? loc["tx.coinbase.newcoins"]
: counterparties.Count > 0
? string.Join(Environment.NewLine, counterparties)
: "—";
// Debito (uscita verso terzi) o Credito (entrata netta sui nostri output).
// Debit (outflow to third parties) or Credit (net inflow on our outputs).
AmountHeader = d.IsIncoming ? loc["tx.credit"] : loc["tx.debit"];
AmountText = d.IsIncoming
? Signed(d.ReceivedSats)