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:
@@ -3,16 +3,16 @@ using System.Text.Json;
|
||||
namespace PalladiumWallet.Core.Storage;
|
||||
|
||||
/// <summary>
|
||||
/// Configurazione globale dell'applicazione (blueprint §8), separata dai file
|
||||
/// wallet: lingua, unità di visualizzazione, ecc. Persistita in config.json
|
||||
/// nella radice dei dati (vale per tutte le reti).
|
||||
/// Global application configuration (blueprint §8), separate from wallet
|
||||
/// files: language, display unit, etc. Persisted in config.json
|
||||
/// in the data root (applies to all networks).
|
||||
/// </summary>
|
||||
public sealed class AppConfig
|
||||
{
|
||||
/// <summary>Codice lingua UI.</summary>
|
||||
/// <summary>UI language code.</summary>
|
||||
public string Language { get; set; } = "en";
|
||||
|
||||
/// <summary>Unità di visualizzazione degli importi (vedi <see cref="Wallet.CoinAmount.Units"/>).</summary>
|
||||
/// <summary>Display unit for amounts (see <see cref="Wallet.CoinAmount.Units"/>).</summary>
|
||||
public string Unit { get; set; } = "PLM";
|
||||
|
||||
private static readonly JsonSerializerOptions JsonOptions = new() { WriteIndented = true };
|
||||
@@ -28,7 +28,7 @@ public sealed class AppConfig
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
// Config corrotta: si riparte dai default senza bloccare l'avvio.
|
||||
// Corrupted config: fall back to defaults without blocking startup.
|
||||
return new AppConfig();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,29 +3,29 @@ using PalladiumWallet.Core.Chain;
|
||||
namespace PalladiumWallet.Core.Storage;
|
||||
|
||||
/// <summary>
|
||||
/// Percorsi dati per piattaforma (blueprint §8). La radice dati può essere:
|
||||
/// 1. <b>portable</b>: cartella "palladium-data" accanto all'eseguibile;
|
||||
/// 2. <b>personalizzata</b>: scelta dall'utente al primo avvio e memorizzata in
|
||||
/// un piccolo file "puntatore" in una posizione di bootstrap fissa;
|
||||
/// 3. <b>legacy</b>: vecchia posizione (%APPDATA%/PalladiumWallet) se contiene già dati;
|
||||
/// 4. <b>default</b>: ~/.PalladiumWallet (Linux/macOS) o %ProgramFiles%\PalladiumWallet (Windows).
|
||||
/// Sotto la radice c'è una sottocartella per rete (config, wallet, header, certificati).
|
||||
/// Per-platform data paths (blueprint §8). The data root can be:
|
||||
/// 1. <b>portable</b>: "palladium-data" folder next to the executable;
|
||||
/// 2. <b>custom</b>: chosen by the user at first launch and stored in
|
||||
/// a small "pointer" file at a fixed bootstrap location;
|
||||
/// 3. <b>legacy</b>: old location (%APPDATA%/PalladiumWallet) if it already holds data;
|
||||
/// 4. <b>default</b>: ~/.PalladiumWallet (Linux/macOS) or %ProgramFiles%\PalladiumWallet (Windows).
|
||||
/// Under the root there is a per-network subfolder (config, wallet, header, certificates).
|
||||
/// </summary>
|
||||
public static class AppPaths
|
||||
{
|
||||
public const string PortableDirName = "palladium-data";
|
||||
|
||||
/// <summary>Nome cartella applicazione, usato nei vari percorsi.</summary>
|
||||
/// <summary>Application folder name, used in the various paths.</summary>
|
||||
public const string AppDirName = "PalladiumWallet";
|
||||
|
||||
/// <summary>Override esplicito della radice dati (es. CLI --data-dir). Ha priorità su tutto.</summary>
|
||||
/// <summary>Explicit override of the data root (e.g. CLI --data-dir). Takes priority over everything.</summary>
|
||||
public static string? OverrideDataRoot { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Radice dati predefinita, secondo la convenzione di ogni piattaforma:
|
||||
/// Windows → %APPDATA%\PalladiumWallet (PascalCase, come Electrum/Bitcoin);
|
||||
/// Linux/macOS → ~/.palladium-wallet (dotfolder minuscolo, come ~/.bitcoin).
|
||||
/// Per-utente e sempre scrivibile, senza privilegi di amministratore.
|
||||
/// Default data root, following each platform's convention:
|
||||
/// Windows → %APPDATA%\PalladiumWallet (PascalCase, like Electrum/Bitcoin);
|
||||
/// Linux/macOS → ~/.palladium-wallet (lowercase dotfolder, like ~/.bitcoin).
|
||||
/// Per-user and always writable, without administrator privileges.
|
||||
/// </summary>
|
||||
public static string DefaultDataRoot()
|
||||
{
|
||||
@@ -37,8 +37,8 @@ public static class AppPaths
|
||||
return Path.Combine(home, ".palladium-wallet");
|
||||
}
|
||||
|
||||
/// <summary>File puntatore alla radice dati scelta dall'utente. Vive in una
|
||||
/// posizione di bootstrap sempre scrivibile e indipendente dalla radice dati.</summary>
|
||||
/// <summary>Pointer file to the user-chosen data root. Lives at a
|
||||
/// bootstrap location that is always writable and independent of the data root.</summary>
|
||||
private static string LocationPointerPath() =>
|
||||
Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
||||
@@ -50,7 +50,7 @@ public static class AppPaths
|
||||
private static bool HasData(string root) =>
|
||||
Directory.Exists(root) && Directory.EnumerateFileSystemEntries(root).Any();
|
||||
|
||||
/// <summary>Radice dati effettiva, secondo l'ordine di precedenza documentato in classe.</summary>
|
||||
/// <summary>Effective data root, following the precedence order documented on the class.</summary>
|
||||
public static string DataRoot()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(OverrideDataRoot))
|
||||
@@ -67,9 +67,9 @@ public static class AppPaths
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// true se la posizione dei dati è già determinata e non serve chiederla
|
||||
/// all'utente: modalità portable, override, puntatore già scritto, oppure
|
||||
/// dati già presenti nella posizione predefinita.
|
||||
/// true if the data location is already determined and need not be asked
|
||||
/// of the user: portable mode, override, pointer already written, or
|
||||
/// data already present at the default location.
|
||||
/// </summary>
|
||||
public static bool IsDataLocationConfigured() =>
|
||||
!string.IsNullOrEmpty(OverrideDataRoot)
|
||||
@@ -77,7 +77,7 @@ public static class AppPaths
|
||||
|| ReadPointer() is not null
|
||||
|| HasData(DefaultDataRoot());
|
||||
|
||||
/// <summary>Memorizza la radice dati scelta dall'utente e la crea su disco.</summary>
|
||||
/// <summary>Stores the user-chosen data root and creates it on disk.</summary>
|
||||
public static void ConfigureDataLocation(string root)
|
||||
{
|
||||
root = Path.GetFullPath(root.Trim());
|
||||
@@ -96,7 +96,7 @@ public static class AppPaths
|
||||
return string.IsNullOrEmpty(path) ? null : path;
|
||||
}
|
||||
|
||||
/// <summary>Cartella dati della rete (config, wallet, header, certificati).</summary>
|
||||
/// <summary>Network data folder (config, wallet, header, certificates).</summary>
|
||||
public static string ForNetwork(NetKind net)
|
||||
{
|
||||
var dir = Path.Combine(DataRoot(), ChainProfiles.For(net).NetName);
|
||||
@@ -114,7 +114,7 @@ public static class AppPaths
|
||||
public static string DefaultWalletPath(NetKind net) =>
|
||||
Path.Combine(WalletsDir(net), "default.wallet.json");
|
||||
|
||||
/// <summary>Tutti i file wallet della rete, ordinati per nome (multi-wallet §8).</summary>
|
||||
/// <summary>All wallet files for the network, ordered by name (multi-wallet §8).</summary>
|
||||
public static IReadOnlyList<string> WalletFiles(NetKind net)
|
||||
{
|
||||
var dir = WalletsDir(net);
|
||||
|
||||
@@ -5,9 +5,9 @@ using System.Text.Json;
|
||||
namespace PalladiumWallet.Core.Storage;
|
||||
|
||||
/// <summary>
|
||||
/// Cifratura del file wallet (blueprint §8/§17): AES-256-GCM con chiave derivata
|
||||
/// dalla password via PBKDF2-HMAC-SHA512. Il contenitore è JSON autodescrittivo
|
||||
/// (kdf, parametri, salt, nonce) per consentire upgrade futuri dei parametri.
|
||||
/// Wallet file encryption (blueprint §8/§17): AES-256-GCM with a key derived
|
||||
/// from the password via PBKDF2-HMAC-SHA512. The container is self-describing JSON
|
||||
/// (kdf, parameters, salt, nonce) to allow future parameter upgrades.
|
||||
/// </summary>
|
||||
public static class EncryptedFile
|
||||
{
|
||||
@@ -54,7 +54,7 @@ public static class EncryptedFile
|
||||
Convert.ToBase64String(tag), Convert.ToBase64String(cipher)));
|
||||
}
|
||||
|
||||
/// <summary>Lancia <see cref="WrongPasswordException"/> se la password è errata o il file è manomesso.</summary>
|
||||
/// <summary>Throws <see cref="WrongPasswordException"/> if the password is wrong or the file is tampered with.</summary>
|
||||
public static string Decrypt(string fileContent, string password)
|
||||
{
|
||||
var container = JsonSerializer.Deserialize<Container>(fileContent)
|
||||
@@ -74,7 +74,7 @@ public static class EncryptedFile
|
||||
}
|
||||
catch (AuthenticationTagMismatchException)
|
||||
{
|
||||
// Il tag GCM autentica: password errata e manomissione sono indistinguibili.
|
||||
// The GCM tag authenticates: a wrong password and tampering are indistinguishable.
|
||||
throw new WrongPasswordException();
|
||||
}
|
||||
finally
|
||||
@@ -88,7 +88,7 @@ public static class EncryptedFile
|
||||
Rfc2898DeriveBytes.Pbkdf2(password, salt, iterations, HashAlgorithmName.SHA512, KeySize);
|
||||
}
|
||||
|
||||
/// <summary>Password errata (o file wallet manomesso: il tag GCM non distingue i due casi).</summary>
|
||||
/// <summary>Wrong password (or tampered wallet file: the GCM tag does not distinguish the two cases).</summary>
|
||||
public sealed class WrongPasswordException : Exception
|
||||
{
|
||||
public WrongPasswordException() : base("Password errata o file wallet danneggiato.") { }
|
||||
|
||||
@@ -4,9 +4,9 @@ using System.Text.Json.Serialization;
|
||||
namespace PalladiumWallet.Core.Storage;
|
||||
|
||||
/// <summary>
|
||||
/// Schema del file wallet (blueprint §8), versionato per consentire migrazioni
|
||||
/// automatiche all'apertura. La cifratura (quando c'è una password) avvolge
|
||||
/// l'intero documento via <see cref="EncryptedFile"/>.
|
||||
/// Wallet file schema (blueprint §8), versioned to allow automatic
|
||||
/// migrations on opening. Encryption (when there is a password) wraps
|
||||
/// the entire document via <see cref="EncryptedFile"/>.
|
||||
/// </summary>
|
||||
public sealed class WalletDocument
|
||||
{
|
||||
@@ -14,42 +14,42 @@ public sealed class WalletDocument
|
||||
|
||||
public int Version { get; set; } = CurrentVersion;
|
||||
|
||||
/// <summary>Nome rete (mainnet/testnet/regtest), come ChainProfile.NetName.</summary>
|
||||
/// <summary>Network name (mainnet/testnet/regtest), as ChainProfile.NetName.</summary>
|
||||
public required string Network { get; set; }
|
||||
|
||||
/// <summary>Tipo di script (nome dell'enum ScriptKind).</summary>
|
||||
/// <summary>Script type (name of the ScriptKind enum).</summary>
|
||||
public required string ScriptKind { get; set; }
|
||||
|
||||
/// <summary>Mnemonica BIP39 in chiaro nel documento (il documento va cifrato!); null se watch-only.</summary>
|
||||
/// <summary>BIP39 mnemonic in plaintext in the document (the document must be encrypted!); null if watch-only.</summary>
|
||||
public string? Mnemonic { get; set; }
|
||||
|
||||
/// <summary>Extension word BIP39 (§4.1); null se assente.</summary>
|
||||
/// <summary>BIP39 extension word (§4.1); null if absent.</summary>
|
||||
public string? Passphrase { get; set; }
|
||||
|
||||
/// <summary>Path di account (es. "84'/746'/0'"); null per importati WIF.</summary>
|
||||
/// <summary>Account path (e.g. "84'/746'/0'"); null for imported WIF.</summary>
|
||||
public string? AccountPath { get; set; }
|
||||
|
||||
/// <summary>Xpub di account in SLIP-132 per i wallet HD; null per importati WIF.</summary>
|
||||
/// <summary>Account xpub in SLIP-132 for HD wallets; null for imported WIF.</summary>
|
||||
public string? AccountXpub { get; set; }
|
||||
|
||||
/// <summary>Xprv di account in SLIP-132; presente solo per import da xprv senza seed.</summary>
|
||||
/// <summary>Account xprv in SLIP-132; present only for import from xprv without seed.</summary>
|
||||
public string? AccountXprv { get; set; }
|
||||
|
||||
public string? MasterFingerprint { get; set; }
|
||||
|
||||
/// <summary>Chiavi WIF importate (in chiaro nel documento — va cifrato!).</summary>
|
||||
/// <summary>Imported WIF keys (in plaintext in the document — must be encrypted!).</summary>
|
||||
public List<string>? WifKeys { get; set; }
|
||||
|
||||
/// <summary>Gap limit per la scansione indirizzi (§5), configurabile.</summary>
|
||||
/// <summary>Gap limit for address scanning (§5), configurable.</summary>
|
||||
public int GapLimit { get; set; } = 20;
|
||||
|
||||
/// <summary>Etichette per indirizzo/txid (§12).</summary>
|
||||
/// <summary>Labels by address/txid (§12).</summary>
|
||||
public Dictionary<string, string> Labels { get; set; } = [];
|
||||
|
||||
/// <summary>Rubrica contatti (nome + indirizzo blockchain).</summary>
|
||||
/// <summary>Contact address book (name + blockchain address).</summary>
|
||||
public List<StoredContact> Contacts { get; set; } = [];
|
||||
|
||||
/// <summary>Cache dell'ultimo stato sincronizzato (saldo/storico mostrabili offline).</summary>
|
||||
/// <summary>Cache of the last synced state (balance/history viewable offline).</summary>
|
||||
public SyncCache? Cache { get; set; }
|
||||
|
||||
public bool IsWatchOnly =>
|
||||
@@ -69,6 +69,7 @@ public sealed class WalletDocument
|
||||
{
|
||||
var doc = JsonSerializer.Deserialize<WalletDocument>(json, JsonOptions)
|
||||
?? throw new InvalidDataException("File wallet non valido.");
|
||||
// string literal above intentionally left untranslated
|
||||
return Migrate(doc);
|
||||
}
|
||||
|
||||
@@ -101,28 +102,28 @@ public sealed class SyncCache
|
||||
public List<CachedAddress> Addresses { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Cache raw delle transazioni confermate (txid → hex). Evita di riscaricale
|
||||
/// ad ogni avvio dell'app: le tx confermate sono immutabili per definizione.
|
||||
/// Popolata anche parzialmente in caso di sync interrotta (es. -101):
|
||||
/// il synchronizer riprende dal punto in cui si era fermato.
|
||||
/// Raw transaction cache (txid → hex). Avoids re-downloading confirmed
|
||||
/// transactions on every launch: confirmed txs are immutable by definition.
|
||||
/// May be partially populated after an interrupted sync (e.g. -101 error);
|
||||
/// the synchronizer resumes from where it left off.
|
||||
/// </summary>
|
||||
public Dictionary<string, string>? RawTxHex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Prove di Merkle già verificate (txid → altezza blocco). Evita di
|
||||
/// riverificare le stesse prove ad ogni avvio: le conferme sono immutabili.
|
||||
/// Already-verified Merkle proofs (txid → block height). Avoids re-verifying
|
||||
/// the same proofs on every launch: confirmations are immutable.
|
||||
/// </summary>
|
||||
public Dictionary<string, int>? VerifiedAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Header grezzi per altezza (altezza → hex). Immutabili: non vengono mai
|
||||
/// rifetchati una volta salvati. Elimina i GetBlockHeader sulle prove Merkle
|
||||
/// già verificate nei sync successivi.
|
||||
/// Raw headers by height (height → hex). Immutable: never re-fetched once saved.
|
||||
/// Eliminates GetBlockHeader calls for Merkle proofs already verified in
|
||||
/// subsequent syncs.
|
||||
/// </summary>
|
||||
public Dictionary<int, string>? BlockHeaders { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>Indirizzo scansionato con saldo proprio e numero di transazioni (vista indirizzi).</summary>
|
||||
/// <summary>Scanned address with its own balance and transaction count (address view).</summary>
|
||||
public sealed class CachedAddress
|
||||
{
|
||||
public required string Address { get; set; }
|
||||
|
||||
Reference in New Issue
Block a user