From 4c71eaca2d811fb82a512d1f0dd1689e6500c6e1 Mon Sep 17 00:00:00 2001 From: le king fu Date: Sat, 25 Apr 2026 14:38:09 -0400 Subject: [PATCH] feat(balance): add i18n keys + CHANGELOG entry Adds the FR/EN translation namespace `balance.*` covering: - balance.accountsPage.* (page chrome, tab labels, empty states) - balance.account.* (table fields, status badges, action labels, full account form copy with priced/simple-aware hints) - balance.category.* (intro text, table fields, kind labels, origin labels, action prompts, simple-only creation form, seeded labels for the 7 standard categories) - balance.errors.* (one entry per BalanceErrorCode union member) CHANGELOG.md and CHANGELOG.fr.md both gain a single entry under `[Unreleased] / Added` summarising the schema migration v9, the new balance.service CRUD section and the AccountsPage tabs. Refs #138 Co-Authored-By: Claude Opus 4.7 (1M context) --- CHANGELOG.fr.md | 3 ++ CHANGELOG.md | 3 ++ src/i18n/locales/en.json | 95 ++++++++++++++++++++++++++++++++++++++++ src/i18n/locales/fr.json | 95 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 196 insertions(+) diff --git a/CHANGELOG.fr.md b/CHANGELOG.fr.md index 5d3fcf9..7415247 100644 --- a/CHANGELOG.fr.md +++ b/CHANGELOG.fr.md @@ -2,6 +2,9 @@ ## [Non publié] +### Ajouté +- **Bilan — fondations du schéma et page Comptes** (route `/balance/accounts`) : première tranche de la nouvelle feature *Bilan*. La migration SQL v9 introduit 5 tables (`balance_categories`, `balance_accounts`, `balance_snapshots`, `balance_snapshot_lines`, `balance_account_transfers`) avec 7 index et seede 7 catégories standard — Encaisse, CELI, REER, Fonds commun, Autre (type simple) + Action et Cryptomonnaie (type coté). La colonne `currency` est verrouillée à `CAD` via une contrainte CHECK au MVP — le support multi-devises arrivera plus tard. La nouvelle page expose deux onglets : *Comptes* (CRUD complet sur les comptes de l'utilisateur, archivage soft plutôt que suppression dure pour préserver les snapshots historiques) et *Catégories* (renommer une catégorie, créer des catégories de type simple, supprimer celles créées par l'utilisateur — les catégories standard sont protégées). Couverture i18n FR/EN complète sous `balance.*`. Snapshots, transferts, rendements et price-fetching premium arriveront dans les prochaines issues ; pour l'instant la route est accessible directement par URL (pas encore d'entrée sidebar) (#138) + ### Corrigé - **Rapport Zoom catégorie** (`/reports/category`) : la liste déroulante du combobox des catégories affiche désormais la liste complète dans un ordre hiérarchique DFS correct — chaque racine est émise avant ses descendants, et les frères et sœurs sont triés par `sort_order` puis nom affiché. Auparavant la liste était triée globalement par `sort_order` (via un `ORDER BY sort_order, name` SQL), ce qui entrelaçait des parents et enfants de sous-arbres différents partageant le même `sort_order`, d'où l'indentation incohérente et l'impression d'arbre cassé. La recherche filtrée (insensible aux accents) conserve le même comportement (#126) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1511e35..66f4e04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## [Unreleased] +### Added +- **Balance sheet — schema foundation and accounts page** (route `/balance/accounts`): first slice of the upcoming *Bilan* feature. New SQL migration v9 introduces 5 tables (`balance_categories`, `balance_accounts`, `balance_snapshots`, `balance_snapshot_lines`, `balance_account_transfers`) with 7 indexes and seeds 7 standard categories — Cash, TFSA, RRSP, Mutual Fund, Other (simple kind) plus Stock and Crypto (priced kind). The `currency` column is hardcoded to `CAD` via a CHECK constraint at the MVP — multi-currency support will come in a later release. The new accounts page exposes two tabs: *Accounts* (full CRUD over the user's holdings, soft-archive instead of hard delete to preserve historic snapshots) and *Categories* (rename any category, create simple-kind ones, delete user-created ones — seeded categories are protected). The full FR/EN i18n coverage uses keys under `balance.*`. Snapshots, transfers, returns and the price-fetching premium remain to ship in upcoming issues; for now the route is reachable directly via URL (no sidebar entry yet) (#138) + ### Fixed - **Category zoom report** (`/reports/category`): the category combobox dropdown now renders the full list in proper hierarchical DFS order — each root is emitted before its descendants, with siblings sorted by `sort_order` then display name. Previously the list was ordered by `sort_order` globally (from a SQL `ORDER BY sort_order, name`), which interleaved parents and children from different sub-trees that shared the same `sort_order`, producing scrambled indentation and a mis-leading tree. Filtering (accent-insensitive search) still behaves identically (#126) diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index 3ac5f0f..7a1f03a 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -1449,5 +1449,100 @@ } } } + }, + "balance": { + "accountsPage": { + "title": "Balance accounts", + "tabs": { + "accounts": "Accounts", + "categories": "Categories" + }, + "newAccount": "New account", + "includeArchived": "Show archived accounts", + "empty": "No accounts yet. Click “New account” to start." + }, + "account": { + "fields": { + "name": "Name", + "category": "Category", + "symbol": "Symbol", + "currency": "Currency", + "status": "Status", + "actions": "Actions" + }, + "status": { + "active": "Active", + "archived": "Archived" + }, + "actions": { + "archive": "Archive", + "unarchive": "Restore" + }, + "form": { + "createTitle": "New account", + "editTitle": "Edit account", + "category": "Category", + "noCategory": "(no category available)", + "name": "Account name", + "nameRequired": "Name is required.", + "symbol": "Symbol", + "symbolPricedHint": "required for priced categories", + "symbolPlaceholderSimple": "Optional", + "symbolPlaceholderPriced": "e.g. AAPL, BTC-USD", + "notes": "Notes", + "currencyMvpNotice": "At the MVP, all accounts are in CAD. Multi-currency support will land in a later version.", + "save": "Save", + "create": "Create account" + } + }, + "category": { + "intro": "Seeded categories (TFSA, RRSP, Cash, etc.) ship with the app. You can create your own for special cases.", + "fields": { + "name": "Name", + "key": "Key", + "kind": "Kind", + "origin": "Origin", + "actions": "Actions" + }, + "kind": { + "simple": "Direct amount", + "priced": "Quantity × price" + }, + "origin": { + "seeded": "Standard", + "user": "Custom" + }, + "actions": { + "create": "New category", + "renamePrompt": "New label for this category", + "deleteConfirm": "Delete this category? This cannot be undone.", + "deleteSeedHint": "Standard categories cannot be deleted." + }, + "form": { + "createTitle": "New category", + "key": "Key", + "keyPlaceholder": "e.g. lira, prpp", + "label": "Label", + "labelPlaceholder": "e.g. LIRA, PRPP", + "simpleOnlyNotice": "Priced categories (stocks, crypto) will be available in a future release.", + "create": "Create category" + }, + "cash": "Cash", + "tfsa": "TFSA", + "rrsp": "RRSP", + "fund": "Mutual fund", + "other": "Other", + "stock": "Stock", + "crypto": "Crypto" + }, + "errors": { + "currency_unsupported": "Only CAD is supported at the MVP.", + "category_seed_protected": "Standard categories cannot be deleted.", + "category_has_accounts": "Cannot delete a category with linked accounts. Move or archive linked accounts first.", + "category_not_found": "Category not found.", + "account_not_found": "Account not found.", + "name_required": "Name is required.", + "kind_invalid": "Invalid category kind." + } } } diff --git a/src/i18n/locales/fr.json b/src/i18n/locales/fr.json index e5b8c80..d5b5f8a 100644 --- a/src/i18n/locales/fr.json +++ b/src/i18n/locales/fr.json @@ -1449,5 +1449,100 @@ } } } + }, + "balance": { + "accountsPage": { + "title": "Comptes du bilan", + "tabs": { + "accounts": "Comptes", + "categories": "Catégories" + }, + "newAccount": "Nouveau compte", + "includeArchived": "Afficher les comptes archivés", + "empty": "Aucun compte pour l'instant. Cliquez sur « Nouveau compte » pour commencer." + }, + "account": { + "fields": { + "name": "Nom", + "category": "Catégorie", + "symbol": "Symbole", + "currency": "Devise", + "status": "Statut", + "actions": "Actions" + }, + "status": { + "active": "Actif", + "archived": "Archivé" + }, + "actions": { + "archive": "Archiver", + "unarchive": "Restaurer" + }, + "form": { + "createTitle": "Nouveau compte", + "editTitle": "Modifier le compte", + "category": "Catégorie", + "noCategory": "(aucune catégorie disponible)", + "name": "Nom du compte", + "nameRequired": "Le nom est obligatoire.", + "symbol": "Symbole", + "symbolPricedHint": "obligatoire pour cette catégorie cotée", + "symbolPlaceholderSimple": "Optionnel", + "symbolPlaceholderPriced": "ex. AAPL, BTC-USD", + "notes": "Notes", + "currencyMvpNotice": "Au MVP, tous les comptes sont en CAD. Le support multi-devises arrivera dans une version ultérieure.", + "save": "Enregistrer", + "create": "Créer le compte" + } + }, + "category": { + "intro": "Les catégories seedées (CELI, REER, Encaisse, etc.) sont fournies par l'application. Vous pouvez en créer de nouvelles pour vos cas particuliers.", + "fields": { + "name": "Nom", + "key": "Clé", + "kind": "Type", + "origin": "Origine", + "actions": "Actions" + }, + "kind": { + "simple": "Montant direct", + "priced": "Quantité × prix" + }, + "origin": { + "seeded": "Standard", + "user": "Personnalisée" + }, + "actions": { + "create": "Nouvelle catégorie", + "renamePrompt": "Nouveau libellé pour cette catégorie", + "deleteConfirm": "Supprimer cette catégorie ? Cette action est irréversible.", + "deleteSeedHint": "Les catégories standard ne peuvent pas être supprimées." + }, + "form": { + "createTitle": "Nouvelle catégorie", + "key": "Clé", + "keyPlaceholder": "ex. ferr, rpdb", + "label": "Libellé", + "labelPlaceholder": "ex. FERR, RPDB", + "simpleOnlyNotice": "Les catégories cotées (actions, crypto) seront disponibles dans une prochaine version.", + "create": "Créer la catégorie" + }, + "cash": "Encaisse", + "tfsa": "CELI", + "rrsp": "REER", + "fund": "Fonds commun", + "other": "Autre", + "stock": "Action", + "crypto": "Cryptomonnaie" + }, + "errors": { + "currency_unsupported": "Seul le CAD est supporté au MVP.", + "category_seed_protected": "Les catégories standard ne peuvent pas être supprimées.", + "category_has_accounts": "Impossible de supprimer une catégorie avec des comptes liés. Déplacez ou archivez d'abord les comptes liés.", + "category_not_found": "Catégorie introuvable.", + "account_not_found": "Compte introuvable.", + "name_required": "Le nom est obligatoire.", + "kind_invalid": "Type de catégorie invalide." + } } }