# Adding a new language Reference: implemented PT (default) + EN (`/en`). Next planned: ES (`/es`). ## Architecture overview - Language is URL-prefix based: `/en/...`, `/es/...` - No cookies, no sessions — URL is the source of truth - Language detected in `_Layout.cshtml` via `Context.Request.Path` - Pages without a translation simply don't get hreflang tags ## Checklist to add a new language (e.g. `/es`) ### 1. Create page files Mirror the `Pages/En/` folder structure: ``` Pages/Es/ Index.cshtml + Index.cshtml.cs → @page "/es" Pricing.cshtml + Pricing.cshtml.cs → @page "/es/pricing" Playground.cshtml + Playground.cshtml.cs → @page "/es/playground" Validators/ Index.cshtml + Index.cshtml.cs → @page "/es/validators" Docs/ Index.cshtml + Index.cshtml.cs → @page "/es/docs" Quickstart.cshtml + .cs → @page "/es/docs/quickstart" ApiReference.cshtml + .cs → @page "/es/docs/api-reference" Mcp.cshtml + .cs → @page "/es/docs/mcp" N8n.cshtml + .cs → @page "/es/docs/n8n" Credits.cshtml + .cs → @page "/es/docs/credits" Errors.cshtml + .cs → @page "/es/docs/errors" ``` **Validator ordering for ES:** Universal first (same as EN), Brazilian second. ### 2. Update `_Layout.cshtml` File: `src/Nalu.Web/Pages/_Layout.cshtml` #### a) Language detection block (top `@{ }`) Add ES detection alongside EN: ```csharp var _isEn = Context.Request.Path.StartsWithSegments("/en"); var _isEs = Context.Request.Path.StartsWithSegments("/es"); // ADD var _lp = _isEn ? "/en" : _isEs ? "/es" : ""; // UPDATE ``` #### b) Known pages sets — add ES set ```csharp var _knownEs = new HashSet { "/es", "/es/pricing", "/es/validators", "/es/playground", "/es/docs", "/es/docs/quickstart", "/es/docs/api-reference", "/es/docs/mcp", "/es/docs/n8n", "/es/docs/credits", "/es/docs/errors" }; bool _hasAlternate = (_isEn ? _knownEn : _isEs ? _knownEs : _knownPt).Contains(_cur); ``` #### c) `_altUrl` switch — add ES cases to all three branches The switch currently has EN→PT and PT→EN. Add: - EN→ES branch (or link via PT as pivot) - ES→PT branch - PT→ES branch Simplest: each language maps to PT as canonical pivot, then PT maps to all others. Or: extend the switch to map directly between all pairs. Given 3 languages, direct mapping is cleaner: ```csharp // When on ES page, altUrl = PT equivalent "/es" => "/", "/es/pricing" => "/precos", // ... etc // When on PT page, need to decide which alternate to link to. // Convention: globe shows the "other" language not currently active. // With 3 languages, globe becomes a dropdown with all options. ``` #### d) Globe dropdown — extend to 3 options Replace the current 2-option globe with a 3-option dropdown: ```html 🇧🇷 Português @(_isEn || _isEs ? "" : "✓") 🇺🇸 English @(_isEn ? "✓" : "") 🇪🇸 Español @(_isEs ? "✓" : "") ``` You'll need to compute both `_altUrlEn` and `_altUrlEs` (and `_altUrlPt`) separately instead of a single `_altUrl`. #### e) Nav link labels — add ES strings ```csharp // Current: @(_isEn ? "Validators" : "Validadores") // Updated: @(_isEn ? "Validators" : _isEs ? "Validadores" : "Validadores") // Most validator names are the same in ES/PT — adjust as needed. ``` Pricing label: ```csharp @(_isEn ? "Pricing" : _isEs ? "Precios" : "Preços") ``` #### f) Footer — add ES to use cases section Currently the "Casos/Use cases" section links to PT-only `/casos/...` pages. For ES, either link to the same PT pages or create ES case study pages. #### g) hreflang — add ES alternate ```csharp // _esAbsolute = ES version URL ``` #### h) `html lang` attribute ```csharp ``` ### 3. Logo link Currently: ```csharp ``` Update: ```csharp ``` ### 4. Pricing page — currency ES pricing: same USD values as EN page (`/en/pricing` as reference). Spanish-speaking markets outside Brazil → use USD, show BRL as `≈ R$ X` secondary (same pattern as EN). Or: if targeting Spain specifically, consider EUR. Decision needed per market. ### 5. Validators ordering | Language | Order | |----------|-------| | PT | Brazilian first, Universal second | | EN | Universal first, Brazilian second | | ES | Universal first, Brazilian second (same as EN) | ### 6. PT pages without EN equivalent Pages like `/casos/parcelas-48x`, `/docs/fluxos`, `/validadores/reply` have no EN/ES version. Globe dropdown on these pages shows links to EN/ES home (`/en`, `/es`) as fallback. This is intentional. ## URL slug conventions | Concept | PT | EN | ES (planned) | |-------------|--------------|----------------|--------------| | Home | `/` | `/en` | `/es` | | Pricing | `/precos` | `/en/pricing` | `/es/precios`| | Validators | `/validadores`| `/en/validators`| `/es/validadores`| | Playground | `/playground`| `/en/playground`| `/es/playground`| | Docs | `/docs` | `/en/docs` | `/es/docs` | | Credits | `/docs/creditos`| `/en/docs/credits`| `/es/docs/credits`| | Errors | `/docs/erros`| `/en/docs/errors`| `/es/docs/errors`| ## SEO tags (auto-generated in layout) The layout generates these automatically for pages with known translations: ```html ``` `x-default` always points to PT (primary market). Add `hreflang="es"` when ES is implemented. ## Files to touch (summary) When adding ES: 1. `Pages/En/*.cshtml` — duplicate folder as `Pages/Es/`, translate content 2. `Pages/_Layout.cshtml` — 6 locations: detection, known sets, altUrl switch, globe dropdown, nav labels, hreflang tags 3. No changes needed to: PageModels (thin, language-agnostic), API endpoints, auth, Stripe