fix(finance): i18n — fix TOML duplicate key and missing Lang on Translator
- Remove conflicting `analysis = "..."` scalar from [nav] in both en.toml and pt.toml; it shadowed the [nav.analysis] sub-table, causing the TOML parser to reject the entire file at startup - Update nav analysis dropdown label to reuse nav.drawer.analysis_label - Add lang field to Translator and expose T.Lang() method so base.html can highlight the active language in the switcher without requiring a Lang field on every page data struct Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
2166790fab
commit
7aa510e1f5
@ -65,6 +65,7 @@ func flattenTOML(prefix string, node map[string]any, out catalogue) {
|
||||
// Translator wraps a locale lookup and exposes a Get method callable from
|
||||
// Go templates as {{.T.Get "key"}}.
|
||||
type Translator struct {
|
||||
lang string
|
||||
cat catalogue
|
||||
en catalogue
|
||||
}
|
||||
@ -79,13 +80,19 @@ func (tr *Translator) Get(key string) string {
|
||||
return key
|
||||
}
|
||||
|
||||
// Lang returns the active language code for use in templates (e.g. {{.T.Lang}}).
|
||||
func (tr *Translator) Lang() string {
|
||||
return tr.lang
|
||||
}
|
||||
|
||||
// newT returns a Translator for the given language.
|
||||
func newT(lang string) *Translator {
|
||||
cat, ok := catalogues[lang]
|
||||
if !ok {
|
||||
lang = defaultLang
|
||||
cat = catalogues[defaultLang]
|
||||
}
|
||||
return &Translator{cat: cat, en: catalogues[defaultLang]}
|
||||
return &Translator{lang: lang, cat: cat, en: catalogues[defaultLang]}
|
||||
}
|
||||
|
||||
// detectLang reads the lang from a cookie, falling back to Accept-Language,
|
||||
|
||||
@ -8,7 +8,6 @@ portfolio = "Portfolio"
|
||||
goals = "Goals"
|
||||
property = "Property"
|
||||
people = "People"
|
||||
analysis = "Analysis"
|
||||
settings = "Settings"
|
||||
business = "🏢 Business"
|
||||
hub_back = "← Hub"
|
||||
|
||||
@ -8,7 +8,6 @@ portfolio = "Carteira"
|
||||
goals = "Objetivos"
|
||||
property = "Imóveis"
|
||||
people = "Pessoas"
|
||||
analysis = "Análise"
|
||||
settings = "Definições"
|
||||
business = "🏢 Empresa"
|
||||
hub_back = "← Hub"
|
||||
|
||||
@ -584,7 +584,7 @@
|
||||
{{$analysisActive := or (eq .Route "reports") (eq .Route "projections") (eq .Route "networth") (eq .Route "simulator") (eq .Route "tax")}}
|
||||
<div class="nav-group">
|
||||
<button class="nav-group-btn {{if $analysisActive}}active{{end}}">
|
||||
{{.T.Get "nav.analysis"}} <svg viewBox="0 0 10 6" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M1 1l4 4 4-4"/></svg>
|
||||
{{.T.Get "nav.drawer.analysis_label"}} <svg viewBox="0 0 10 6" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M1 1l4 4 4-4"/></svg>
|
||||
</button>
|
||||
<div class="nav-dropdown">
|
||||
<a href="/reports" class="{{if eq .Route "reports"}}active{{end}}">{{.T.Get "nav.analysis.reports"}}</a>
|
||||
@ -614,8 +614,8 @@
|
||||
<span class="nav-email">{{.Email}}</span>
|
||||
<form method="POST" action="/lang" style="display:inline;">
|
||||
<select name="lang" onchange="this.form.submit()" style="font-size:12px; background:var(--bg2); color:var(--text2); border:1px solid var(--border2); border-radius:var(--radius-sm); padding:4px 6px; cursor:pointer;">
|
||||
<option value="en" {{if eq .Lang "en"}}selected{{end}}>EN</option>
|
||||
<option value="pt" {{if eq .Lang "pt"}}selected{{end}}>PT</option>
|
||||
<option value="en" {{if eq (.T.Lang) "en"}}selected{{end}}>EN</option>
|
||||
<option value="pt" {{if eq (.T.Lang) "pt"}}selected{{end}}>PT</option>
|
||||
</select>
|
||||
</form>
|
||||
<button class="theme-btn" id="theme-toggle" title="{{.T.Get "nav.theme.toggle_title"}}">🌙</button>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user