Bilingual EN/FR: i18n.js dict+t(), lang state+payload, header toggle, FR copy, Intl formatters; i18n.test.js + bilingual smoke; FR mobile audit evidence + BILINGUAL-REPORT.md
This commit is contained in:
1 parent
1b194b6f92
commit
ea953ec23c
60 files changed
+2788
-241
No files matched your search
+32
-28
@@ -6,32 +6,35 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="theme-color" content="#f7f9fc">
|
||||
<title>Retire Planner — Canadian retirement, modelled properly</title>
|
||||
<meta name="description" content="A Canadian retirement calculator with real CPP/OAS/GIS/RRIF mechanics and live 2026 tax rates. 100% client-side — answers never leave your browser.">
|
||||
<meta name="description" data-i18n-attr="content:doc.desc" content="A Canadian retirement calculator with real CPP/OAS/GIS/RRIF mechanics and live 2026 tax rates. 100% client-side — answers never leave your browser.">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<header class="hdr">
|
||||
<div class="hdr-in">
|
||||
<span class="logo">🍁 <b>Retire Planner</b></span>
|
||||
<span class="pill" title="No server, no tracking, no accounts">🔒 100% client-side — answers never leave your browser</span>
|
||||
<button id="btn-restart" class="ghost" hidden>Start over</button>
|
||||
<span class="logo">🍁 <b data-i18n="brand">Retire Planner</b></span>
|
||||
<span class="lang-toggle" role="group" aria-label="Language / Langue">
|
||||
<button id="lang-en" class="lang-btn" aria-pressed="true">EN</button><button id="lang-fr" class="lang-btn" aria-pressed="false">FR</button>
|
||||
</span>
|
||||
<span class="pill" data-i18n="hdr.pill" data-i18n-attr="title:hdr.pillTitle" title="No server, no tracking, no accounts">🔒 100% client-side — answers never leave your browser</span>
|
||||
<button id="btn-restart" class="ghost" data-i18n="hdr.startOver" hidden>Start over</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<!-- INTRO -->
|
||||
<section id="scr-intro" class="scr">
|
||||
<h1>Will you actually run out of money?</h1>
|
||||
<p class="lede">Most Canadian retirement calculators stop at “your RRSP grows at 6%”. This one models <b>real CPP/OAS/GIS/RRIF mechanics</b>, provincial taxes fetched live, and the tax cliff most planners won't show you.</p>
|
||||
<h1 data-i18n="intro.h1">Will you actually run out of money?</h1>
|
||||
<p class="lede" data-i18n-html="intro.lede">Most Canadian retirement calculators stop at “your RRSP grows at 6%”. This one models <b>real CPP/OAS/GIS/RRIF mechanics</b>, provincial taxes fetched live, and the tax cliff most planners won't show you.</p>
|
||||
<ul class="ticks">
|
||||
<li>CPP early/late (−0.6%/mo before 65, +0.7% after), OAS deferral, clawback & GIS</li>
|
||||
<li>Live 2026 federal + all 13 province/territory tax tables</li>
|
||||
<li>RRIF minimums at 71, pension splitting, tax-smart drawdown</li>
|
||||
<li>Couples: joint taxes, split pensions, household GIS</li>
|
||||
<li data-i18n="intro.tick1">CPP early/late (−0.6%/mo before 65, +0.7% after), OAS deferral, clawback & GIS</li>
|
||||
<li data-i18n="intro.tick2">Live 2026 federal + all 13 province/territory tax tables</li>
|
||||
<li data-i18n="intro.tick3">RRIF minimums at 71, pension splitting, tax-smart drawdown</li>
|
||||
<li data-i18n="intro.tick4">Couples: joint taxes, split pensions, household GIS</li>
|
||||
</ul>
|
||||
<p class="privacy">🔒 100% client-side — answers never leave your browser. No account, no tracking, nothing is sent anywhere.</p>
|
||||
<button id="btn-begin" class="cta">Build my retirement plan →</button>
|
||||
<p class="fine">~2 minutes. Works on one screen at a time; you can change anything later.</p>
|
||||
<p class="privacy" data-i18n="intro.privacy">🔒 100% client-side — answers never leave your browser. No account, no tracking, nothing is sent anywhere.</p>
|
||||
<button id="btn-begin" class="cta" data-i18n="intro.cta">Build my retirement plan →</button>
|
||||
<p class="fine" data-i18n="intro.fine">~2 minutes. Works on one screen at a time; you can change anything later.</p>
|
||||
</section>
|
||||
|
||||
<!-- QUESTIONNAIRE -->
|
||||
@@ -40,14 +43,14 @@
|
||||
<div class="quiz-main">
|
||||
<div class="prog"><div id="prog-bar"></div></div>
|
||||
<div class="step-nav">
|
||||
<button id="btn-back" class="ghost">← Back</button>
|
||||
<button id="btn-back" class="ghost" data-i18n="quiz.back">← Back</button>
|
||||
<span id="step-count" class="step-count"></span>
|
||||
</div>
|
||||
<div id="step-body"></div>
|
||||
<button id="btn-next" class="cta">Next →</button>
|
||||
<button id="btn-next" class="cta" data-i18n="quiz.next">Next →</button>
|
||||
</div>
|
||||
<aside class="panel" id="panel">
|
||||
<div class="panel-h">Your plan so far</div>
|
||||
<div class="panel-h" data-i18n="panel.title">Your plan so far</div>
|
||||
<div id="panel-chips" class="chips"></div>
|
||||
<div id="panel-insight" class="insight"></div>
|
||||
</aside>
|
||||
@@ -59,7 +62,7 @@
|
||||
<!-- RESULTS -->
|
||||
<section id="scr-results" class="scr" hidden>
|
||||
<div id="vision-card" class="vision"></div>
|
||||
<h2 id="verdict-h">Your plan, in one line</h2>
|
||||
<h2 id="verdict-h" data-i18n="r.verdictH">Your plan, in one line</h2>
|
||||
<p id="verdict" class="verdict"></p>
|
||||
|
||||
<div class="cards" id="gap-cards"></div>
|
||||
@@ -72,32 +75,32 @@
|
||||
<p id="g4-note" class="cap"></p>
|
||||
|
||||
<details class="whatif" id="whatif">
|
||||
<summary><b>Try a what-if</b> — move a slider, watch the plan update</summary>
|
||||
<summary data-i18n-html="r.whatif"><b>Try a what-if</b> — move a slider, watch the plan update</summary>
|
||||
<div class="wi-grid">
|
||||
<label>Annual spending <output id="wi-spend-o"></output>
|
||||
<label><span data-i18n="r.wiSpend">Annual spending</span> <output id="wi-spend-o"></output>
|
||||
<input type="range" id="wi-spend" min="20000" max="150000" step="1000"></label>
|
||||
<label>Monthly savings <output id="wi-ctrb-o"></output>
|
||||
<label><span data-i18n="r.wiCtrb">Monthly savings</span> <output id="wi-ctrb-o"></output>
|
||||
<input type="range" id="wi-ctrb" min="0" max="5000" step="50"></label>
|
||||
<label>Retirement age <output id="wi-ret-o"></output>
|
||||
<label><span data-i18n="r.wiRet">Retirement age</span> <output id="wi-ret-o"></output>
|
||||
<input type="range" id="wi-ret" min="55" max="72" step="1"></label>
|
||||
<label>CPP starts at <output id="wi-cpp-o"></output>
|
||||
<label><span data-i18n="r.wiCpp">CPP starts at</span> <output id="wi-cpp-o"></output>
|
||||
<input type="range" id="wi-cpp" min="60" max="70" step="1"></label>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details class="yearly">
|
||||
<summary>Year-by-year detail (<span id="yr-n">0</span> years)</summary>
|
||||
<summary id="yr-summary">Year-by-year detail (<span id="yr-n">0</span> years)</summary>
|
||||
<div class="tbl-wrap"><table id="yr-table"></table></div>
|
||||
</details>
|
||||
|
||||
<div class="disclaimer">
|
||||
<p><b>Estimates only — not financial advice.</b> Simplified model: GIS uses a simplified 50% phase-out; Quebec shown with the 16.5% federal abatement (QPP and Quebec payroll taxes not modelled); DB pensions not modelled; returns are constant real rates; Ontario surtax modelled on base tax.</p>
|
||||
<p data-i18n-html="d.main"><b>Estimates only — not financial advice.</b> Simplified model: GIS uses a simplified 50% phase-out; Quebec shown with the 16.5% federal abatement (QPP and Quebec payroll taxes not modelled); DB pensions not modelled; returns are constant real rates; Ontario surtax modelled on base tax.</p>
|
||||
<p class="stamp" id="stamp">tax rates 2026</p>
|
||||
<p class="privacy">🔒 100% client-side — answers never leave your browser. Your answers are saved only in this browser (localStorage).</p>
|
||||
<p class="privacy" data-i18n="d.privacy">🔒 100% client-side — answers never leave your browser. Your answers are saved only in this browser (localStorage).</p>
|
||||
<div class="btn-row">
|
||||
<button id="btn-print" class="ghost">🖨 Print / save PDF</button>
|
||||
<button id="btn-share" class="ghost">🔗 Copy link with my answers</button>
|
||||
<button id="btn-edit" class="ghost">✎ Edit answers</button>
|
||||
<button id="btn-print" class="ghost" data-i18n="res.print">🖨 Print / save PDF</button>
|
||||
<button id="btn-share" class="ghost" data-i18n="res.share">🔗 Copy link with my answers</button>
|
||||
<button id="btn-edit" class="ghost" data-i18n="res.edit">✎ Edit answers</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -105,6 +108,7 @@
|
||||
|
||||
<script src="engine/canada.js"></script>
|
||||
<script src="engine/engine.js"></script>
|
||||
<script src="i18n.js"></script>
|
||||
<script src="app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user